诺莫20
知识点:
z3使用,算法逆向
开始:
放入IDA:
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // esi
unsigned int v4; // kr00_4
char v5; // bl
unsigned int v6; // eax
char *v7; // edx
char v8; // cl
int v9; // eax
char v11[80]; // [esp+8h] [ebp-A4h]
char v12[80]; // [esp+58h] [ebp-54h]
sub_401020((int)"Please input your flag: ");
sub_401050("%40s", v12);
memset(v11, 0, 0x50u);
v3 = 0;
v4 = strlen(v12);
if ( v4 )
{
do
{
v5 = v12[v3];
v6 = 0;
do
{
v7 = &v11[v6 + v3];
v8 = v5 ^ byte_41C658[v6++];
*v7 += v8; // V11[V6 + V3] += V5 ^ BYTE_41C658[V6++];
// V6++;
}
while ( v6 < 0x20 );
++v3;
}
while ( v3 < v4 );
}
v9 = strcmp(v11, (const char *)&unk_41E8B0);
if ( v9 )
v9 = -(v9 < 0) | 1;
if ( v9 )
puts("No, it isn't.");
else
puts("Yes, it is.");
return 0;
}
逻辑很清晰,只是逆向有迭代,很难,直接使用z3模块
逆向:
from z3 import*
data1 = [0x72, 0xE9, 0x4D, 0xAC, 0xC1, 0xD0, 0x24, 0x6B, 0xB2, 0xF5, 0xFD, 0x45, 0x49, 0x94, 0xDC, 0x10, 0x10, 0x6B, 0xA3, 0xFB, 0x5C, 0x13, 0x17, 0xE4, 0x67, 0xFE, 0x72, 0xA1, 0xC7, 0x04, 0x2B, 0xC2, 0x9D, 0x3F, 0xA7, 0x6C, 0xE7, 0xD0, 0x90, 0x71, 0x36, 0xB3, 0xAB, 0x67, 0xBF, 0x60, 0x30, 0x3E, 0x78, 0xCD, 0x6D, 0x35, 0xC8, 0x55, 0xFF, 0xC0, 0x95, 0x62, 0xE6, 0xBB, 0x57, 0x34, 0x29, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
data2 = [0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x3A, 0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x7B,0x7C,0x7D,0x7E] #"!\"#$%&',27h,'()*+,-./:;<=>?@[\]^_`{|}~"
flag = ""
m = Solver()
B = [BitVec("x%s"%i,8) for i in range(0x22)]
v6 = 0
v11 = [0] * 65
for i in range(0x22):
for j in range(0x20):
v11[j + i] += B[i] ^ data2[j]
for i in range(0x41):
m.add(v11[i] == data1[i])
print(m.check())
c = m.model()
print(c)
flag = ""
for i in range(0x22):
print(c[B[i]],end = ",")
print()
n = [83,89,67,123,52,43,109,105,108,101,43,98,51,103,105,110,43,119,105,116,104,43,115,105,110,103,49,101,43,115,116,101,112,125]
for i in n:
flag += chr(i)
print(flag)
'''
do
{
v5 = v12[i];
v6 = 0;
do
{
v11[V6 + i] = v5 ^ BYTE_41C658[v6];
v6++;
}
while ( v6 < 32 );
++i;
}
while ( i < len(v12) );
'''
解释:
1.BitVec(“x%s”%i,8):
Int #整型
Bool #布尔型
Array #数组
BitVec(‘a’,8) #char型 不一定是8,更具当时环境定制
Real #实型
具体参考
2.为什么是0x22和0x20:
v11中,我们找到的有效数据(到0)一共65个(0x41),byte_41C658中有31(0x20-1)个。使用输入字符的长度为: 65 - 31 = 34(0x22)个
3.z3中python代码中可以将未知数赋值为表达式:
这里v11中元素的类型为:
输出:
<class 'z3.z3.BitVecRef'>
sat
[x9 = 101,
x8 = 108,
x14 = 105,
x28 = 43,
x31 = 101,
x15 = 110,
x27 = 101,
x29 = 115,
x18 = 105,
x22 = 115,
x0 = 83,
x3 = 123,
x7 = 105,
x13 = 103,
x23 = 105,
x11 = 98,
x30 = 116,
x20 = 104,
x1 = 89,
x10 = 43,
x16 = 43,
x25 = 103,
x21 = 43,
x26 = 49,
x32 = 112,
x33 = 125,
x6 = 109,
x2 = 67,
x19 = 116,
x12 = 51,
x24 = 110,
x17 = 119,
x4 = 52,
x5 = 43]
83,89,67,123,52,43,109,105,108,101,43,98,51,103,105,110,43,119,105,116,104,43,115,105,110,103,49,101,43,115,116,101,112,125,
SYC{4+mile+b3gin+with+sing1e+step}
但有个疑问我还没搞懂,如果把data2换成字符串转ascii,就会报错
在简单逆向10中,我们使用了z3