tctf2021 FEA

不算 wp,只是记录一下从这题中学习到的知识

爆破 sha256

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import itertools
import hashlib
import re
from pwn import *
import string
r=remote("111.186.58.164",30212)
proof_of_work_line = r.recvline(keepends=False).decode("utf-8")

enc = re.search('== (.*)',proof_of_work_line).group(1)
strlist=itertools.product(string.ascii_letters+string.digits,repeat=4)
code=""
key="hUsUzJ47UdPwwTns"
enc="ac2b009cf8ab722c6417f0dff94a24434a7d7c43f12da21a042faa34295efe22"
for i in strlist:
code=i[0]+i[1]+i[2]+i[3]
encinfo=hashlib.sha256(str(code+key).encode('utf-8')).hexdigest()
if encinfo == enc:
print(code)
break;

itertools 的简单用法

1.itertools.product(‘ABCD’, repeat = 2) 排列组合(笛卡尔积)

结果:AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

也可以是两个元组排列组合

2.itertools.permutations(‘ABCD’, 2) 所有可能的排列,无重复元素

结果:AB AC AD BA BC BD CA CB CD DA DB DC

3.itertools.combinations(‘ABCD’, 2) 有序,无重复元素

结果:AB AC AD BC BD CD

4.itertools.combinations_with_replacement(‘ABCD’, 2) 有序,元素可重复

结果:AA AB AC AD BB BC BD CC CD DD

用插件去除 ollvm 混淆

​ 插件介绍:https://eshard.com/posts/d810_blog_post_1/

​ 下载地址:https://gitlab.com/eshard/d810

​ 这个插件提供多个 rules 来反混淆,也可以自己添加规则。在这题中使用了对控制流的混淆,勾选这一选项就可以实现反混淆

使用前后对比

用idaPython去除花指令

​ 从简化后的流程看可以知道有两处反调试,还有一处 smc 自解密

​ smc 后 [rbp+s] 指向解密后的代码,因为代码比较长就用脚本提取出来分析

一些 idapython 函数

idaapi:

BADADDR:4294967295 地址上界

del_items(ea, flags=0, nbytes=1, may_destroy=None):Convert item (instruction/data) to unexplored bytes

create_insn(ea, out=None):Create an instruction at the specified address

get_first_cref_from(frm):Get first instruction referenced from the specified instruction

1
2
3
4
5
6
7
8
9
#提取 smc 的代码
from idaapi import *
start=0x00007F96D2BBB000
count = 0x100000
f=open('C:\\Users\\chz\\Desktop\\smc','wb')
for i in range(0,count):
f.write(get_byte(start+i).to_bytes(1,byteorder='big'))
f.close()
print("success")

​ ida 分析后有一大堆花指令,手动分析时间太久考虑用脚本去除

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
#写了一半的去除部分跳转花指令,自动变code脚本
import idaapi
import idc
def undefine(start,end):
curr=start
while curr != idaapi.BADADDR and curr < end:
idaapi.del_items(curr, 8)
curr=curr+1

def make_code(start,end):
curr=start
while curr != idaapi.BADADDR and curr < end:
insn = idaapi.insn_t()
ret = idaapi.create_insn(curr, insn)
if ret == 0:
idaapi.del_items(curr, 8)
idaapi.del_items(curr+1, 8)
ret = idaapi.create_insn(curr, insn)

next_ea = idaapi.get_first_cref_from(curr)
if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F:
curr = curr+1
else:
curr=next_ea
print(curr)

def clear(start,end):
curr=start
while curr != idaapi.BADADDR and curr < end:
insn = idaapi.insn_t()
if idc.GetDisasm(curr)[0:1]=='j' or idc.GetDisasm(curr)[0:4]=='call': #特定地址反汇编
jmp_addr=idc.GetOperandValue(curr,0) #获取操作数
ret = idaapi.create_insn(jmp_addr, insn)
if ret == 0:
idaapi.del_items(jmp_addr, 8)
idaapi.del_items(jmp_addr+2, 8)
idaapi.del_items(jmp_addr+4, 8)
ret = idaapi.create_insn(curr, insn)
next_ea = idaapi.get_first_cref_from(curr)
if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F:
curr = curr+1
else:
curr=next_ea
print(curr)

def nop(start,end):
curr=start
while curr != idaapi.BADADDR and curr < end:
if idc.is_data(curr):
idc.PatchByte(curr,0x90)
next_ea = idaapi.get_first_cref_from(curr)
if (curr<end and next_ea == BADADDR) or curr==0xbf6a or curr==0x17A6F:
curr = curr+1
else:
curr=next_ea
print(curr)

#undefine(0x0,0x224c6)
#make_code(0x0,0x224C6)
#clear(0x22460,0x224c6)
nop(0x0,0x224c6)

​ 但是好像写得有点太复杂了,也没法完全实现自动 patch

参考资料

作者

0wl

发布于

2021-07-07

更新于

2021-11-16

许可协议

评论