angr入门小试(二)

CTF Hitcon 2017 - sakura

Hitcon 2017: sakura

解题分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int i; // [rsp+Ch] [rbp-4h]

// 一共读取400个字节到缓冲区中
for ( i = 0; i <= 19; ++i )
{
a2 = (char **)((char *)&unk_2121E0 + 20 * i);
read(0, a2, 0x14uLL);
}
if ( (unsigned __int8)sub_850((__int64)&unk_2121E0) ) // 验证函数
{
printf("hitcon{");
sub_10FF6("hitcon{", a2);
puts("}");
}
return 0LL;
}

在验证函数sub_850中非常复杂,每一块的验证逻辑又大致相同。验证失败时,会将[rbp+var_1E49]置0,整个验证函数最后会返回[rbp+var_1E49],此值为1时,验证通过

由于开了pie,在IDA中显示的是RVA,先通过idapython将[rbp+var_1E49]的RVA全部找出来

1
2
3
4
5
6
7
8
9
10
11
12
import idc

start_addr = 0x0850
end_addr = 0x010FF5
p = start_addr

avoid_offset = []
while p <= end_addr:
if 'mov [rbp+var_1E49], 0' in idc.GetDisasm(p):
avoid_offset.append(p)
p = idc.next_head(p)
print(avoid_offset)

在angr中,可以设置入口位置在ImageBase + 0x110BA上,然后将400字节的内容直接放在ImageBase + 0x2121E0

1
2
.text:00000000000110BA                 lea     rdi, unk_2121E0
.text:00000000000110C1 call sub_850

验证通过后会调用sub_10FF6来打印flag信息,如下将byte_212040地址的400字节通过sha256转到v2

1
2
3
4
5
6
7
8
9
10
11
12
unsigned __int64 sub_10FF6()
{
int i; // [rsp+Ch] [rbp-34h]
char v2[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v3; // [rsp+38h] [rbp-8h]

v3 = __readfsqword(0x28u);
SHA256(byte_212040, 400LL, v2);
for ( i = 0; i <= 31; ++i )
printf("%02x", (unsigned __int8)v2[i]);
return __readfsqword(0x28u) ^ v3;
}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import angr
import sys
import hashlib

image_base = 0x400000

avoid_offset = [...]
avoid_offset.append(0x0110EC)

proj = angr.Project('sakura', auto_load_libs=False)
state = proj.factory.blank_state(addr=(image_base + 0x110BA))

data, ret_size = state.posix.get_fd(sys.stdin.fileno()).read_data(400)
state.memory.store(image_base + 0x2121E0, data)

# setting state
simgr = proj.factory.simulation_manager(state)
simgr.one_active.options.add(angr.options.LAZY_SOLVES)

simgr.explore(find=(image_base + 0x00110CA), avoid=[item + image_base for item in avoid_offset])

# 获取执行路径上byte_212040地址处的400字节内容
text = simgr.one_found.solver.eval(simgr.one_found.memory.load(image_base + 0x212040, 400), cast_to=bytes)
print(hashlib.sha256(text).hexdigest())

运行结果及时间如下:

1
2
3
4
5
6
pwn@ubuntu:~/workspace$ time python3 exp.py 
6c0d62189adfd27a12289890d5b89c0dc8098bc976ecc3f6d61ec0429cccae61

real 0m48.518s
user 0m47.992s
sys 0m0.526s
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021 lzeroyuee
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信