Self-Modifying Code,(smc)又叫做自解密,是自己取自己地址上的数据解密,加密之后无法反编译
2020网鼎杯jocker
main函数不能F5,因为堆栈不平衡
修改栈指针
找到栈指针出错的地方,alt+k
修改指针指向
修改完之后,还是不平衡,继续修改
给一个写权限
修改好后f5反编译后分析函数,发现encrypt不能转换成伪代码
原因是可能部分指令无法被反编译或者有未设置成指令的数据字节按c将其设置成指令
动态调试,remote windows debug,下断点
分析,scanf接受输入,v7判断输入长度,动态调试跟踪到push ebp
c将db转为code,重新定义函数去掉堆栈不平衡
f5反编译到encrypt函数
所以main函数要求输入的字符串长度为24,wrong函数对前23个字符进行加密,返回result
omg函数比较返回值result和&unk_4030C0的值,也就是v2
跟进全局变量unk_4030C0,发现一串加密后的数据,shift+e
提取数据
提取得到
0x66,0x6B,0x63,0x64,0x7F,0x61,0x67,0x64,0x3B,0x56,0x6B,0x61,0x7B,0x26,0x3B,0x50,0x63,0x5F,0x4D,0x5A,0x71,0x0C,0x37,0x66
再回到encrypt函数中,提取unk_403040的值
0x0E,0x0D,0x09,0x06,0x13,0x05,0x58,0x56,0x3E,0x06,0x0C, 0x3C,0x1F,0x57,0x14,0x6B,0x57,0x59,0x0D
跟进encrypt函数,逆异或
v2 = [0x0E,0x0D,0x09,0x06,0x13,0x05,0x58,0x56,0x3E,0x06,0x0C,0x3C,0x1F,0x57,0x14,0x6B,0x57,0x59,0x0D]
str1 = 'hahahaha_do_you_find_me?'
flag = ''
for i in range(0,len(str1)):
tmp = chr(a1[i]^ord(str1[i]))
print(tmp,end='')
#flag{d07abccf8a410c
继续跟进发现函数finally无法反编译,同decrypt函数,先undefined,然后数字转code,再define新函数,平衡堆栈
函数finally如下:
srand生成随机数,做一个比较,才是正确的 flag
因为'}'和最后一位‘58’异或得到71,猜测v3,v4,v5,v6,v7和71异或得到flag后五位
s = [0x25,0x74,0x70,0x26,0x3a]
flag='flag{d07abccf8a410c'
for i in s:
flag += chr(i^71)
print(flag)
#flag{d07abccf8a410cb37a}
2018网鼎杯SimpleSMC
运行程序
在ida中搜索字符串,定位函数
loc_400BAC()无法反编译,查看汇编有脏字节
nop掉E8之后,新创建函数,sub_400BAC就可以反编译了
反编译后发现函数被异或了
跟进loc_400AA6,发现一串数据,是典型的SMC
分析loc_400AA6,只能假设函数的前7个字节是正常的,push rbp;mov rbp, rsp;sub rsp
sub_400BAC中:
loc_400AA6中:
遇到堆栈不平衡的地方,修改
用两次异或就可以得到key是F1@gChe
should_start = [0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec] #正常的push rbp
sub_start = [0x46, 0x2A, 0x81, 0x01, 0xE7, 0xE3, 0xC1] #loc_400AA6的开头
tmp = [0x55,0x53,0x48,0x83,0xEC,0x08,0x48] #现在的开头
for i in range(7):
print(chr(should_start[i]^sub_start[i]^tmp[i]),end='')
#F1@gChe
动态调试验证函数是可以正常反编译的, aaaaaaaaaaaaaaaaaaaaaF1@gChe,用idc恢复
#include <idc.idc>
static main()
{
auto addr = 0x400AA6;
auto addr_key = 0x41E1B0;
auto a,i = 0;
auto str = "F1@gChe";
for(i=0;i<=0x104;i++)
{
a = i%7;
PatchByte(addr+i,Byte(addr+i)^ord(str[a:a+1]));
PatchByte(addr+i,Byte(addr+i)^Byte(addr_key+i));
}
}
用idc循环异或之后,再新define函数,成功反编译
其中a1是input,sub_4009AE很明显对它进行处理,然后sub_400360进行校验
sub_400A18是自循环
enc=[0x66,0x0A,0x7,0x0B,0x1D,0x8,0x51,0x38,0x1F,0x5C,0x14,0x38,0x30,0x0A,0x1A,0x28,0x39,0x59,0x0C,0x24,0x24,0x22,0x1,0x1F,0x1E,0x73,0x1D,0x3A,0x8,0x5,0x15,0x0A]
def encode(enc,length):
if (length==32):
return 0
else:
for i in range(length):
enc[i+length]^=enc[i]
return encode(enc,length<<1)
encode(enc,1)
print(''.join(map(chr,enc)))
#flag{d0_y0u_Kn*w_5mC_F1@gCheCk?}
本文始发于微信公众号(山警网络空间安全与电子数据取证):跟pumpkin9从0到1学逆向02——SMC逆向
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论