hello X1cT34m

来写一下下
X1cT34m这一届的面试题
这次有幸成为这一届第一个出答案的

题目难度不怎么大
//一开始很大的
因为出题驴出题失误了
先说说总体算法,
首先是填充,这个其实不用管。。。
然后是置换
可以看到内存中有一个置换表
1
置换的操作逆起来也很简单
2
接着就迎来了第一次加密
3
这个加密不难,稍微动动笔就出来了
然后又是一次置换
置换后是第二次加密
4
这个加密上下颠倒一下就是解密了
但有一个恶心点就是这边不能反编译
要自己修一下栈
当然这边有个坑就是这个byte_405040数组
数组在初始化的时候有个类似反调试的操作
6
这边有个堆分配操作
堆的初始值应该是0但是再调试状态下会出现0xBAADF00D
导致数组的值出现问题
最后呢就是cmp了
cmp的值也能找到
5
这边上一下自己的解密代码
这时候肯定是要用c了啊

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
unsigned char byte_405040[64] = {0x6D, 0x94, 0xA9, 0xC8, 0xC5, 0x9C, 0xC1, 0x10, 0x9D, 0x24,
0x59, 0xD8, 0xF5, 0x2C, 0x71, 0x20, 0xCD, 0xB4, 0x09, 0xE8,
0x25, 0xBC, 0x21, 0x30, 0xFD, 0x44, 0xB9, 0xF8, 0x55, 0x4C,
0xD1, 0x40, 0x2D, 0xD4, 0x69, 0x08, 0x85, 0xDC, 0x81, 0x50,
0x5D, 0x64, 0x19, 0x18, 0xB5, 0x6C, 0x31, 0x60, 0x8D, 0xF4,
0xC9, 0x28, 0xE5, 0xFC, 0xE1, 0x70, 0xBD, 0x84, 0x79, 0x38,
0x15, 0x8C, 0x91, 0x80};

unsigned char dest[64]={0x39, 0x10, 0x29, 0x23, 0x25, 0x22, 0x20, 0x21, 0x14, 0x1E,
0x1A, 0x0E, 0x19, 0x31, 0x05, 0x1C, 0x3F, 0x17, 0x2D, 0x2B,
0x1F, 0x03, 0x1D, 0x16, 0x36, 0x0A, 0x1B, 0x2F, 0x3D, 0x2C,
0x32, 0x3C, 0x26, 0x02, 0x0F, 0x27, 0x0B, 0x18, 0x06, 0x35,
0x24, 0x12, 0x28, 0x13, 0x37, 0x0C, 0x0D, 0x2A, 0x30, 0x3A,
0x07, 0x09, 0x01, 0x11, 0x2E, 0x00, 0x33, 0x34, 0x04, 0x15,
0x38, 0x08, 0x3B, 0x3E};
unsigned char result[64]={0xBE, 0x9F, 0x32, 0x15, 0x82, 0x12, 0x91, 0x24, 0xD2, 0xDE,
0xDE, 0xF8, 0xA1, 0x1F, 0xE3, 0x3B, 0x1F, 0xD4, 0x62, 0xD8,
0x5E, 0x91, 0x43, 0xE6, 0x4B, 0xC8, 0x8D, 0x3E, 0xE8, 0x6F,
0x83, 0x37, 0xE5, 0xC5, 0x6D, 0xC8, 0x80, 0xD6, 0x6D, 0x6C,
0x94, 0xBA, 0xEA, 0xC2, 0x67, 0x64, 0x9D, 0x94, 0x0B, 0xCB,
0x21, 0x21, 0x05, 0x79, 0xB1, 0xB5, 0x53, 0x23, 0xB9, 0xA6,
0xAC, 0x36, 0xCB, 0xC3};
unsigned char input[64] = {0xDC, 0x71, 0x48, 0xDC, 0xB6, 0xFB, 0x79, 0x15, 0xCB, 0x31,
0xD8, 0x26, 0xFD, 0x1F, 0x44, 0x1C, 0xBE, 0xD7, 0xCA, 0xEC,
0x06, 0x75, 0x2E, 0x50, 0x7B, 0x63, 0x2E, 0xBB, 0xC9, 0xD4,
0x33, 0xC7, 0xD1, 0xAC, 0xF8, 0x76, 0xEA, 0xE5, 0xBB, 0x28,
0xEF, 0xFF, 0x1C, 0xEA, 0x3B, 0x44, 0xE6, 0xDF, 0xB0, 0x3A,
0x18, 0x4A, 0xCC, 0x57, 0x35, 0xAE, 0xC6, 0x01, 0xCD, 0x56,
0xB3, 0x07, 0x53, 0xD4

};
/*
void sub_4018BF(int a1)
{
for ( *(_DWORD *)(a1 - 12) = 0; *(_DWORD *)(a1 - 12) <= 15; *(_DWORD *)(a1 - 12) += 2 )
{
*(_DWORD *)(a1 - 20) = *(_DWORD *)(4 * *(_DWORD *)(a1 - 12) + a1 - 96);
*(_DWORD *)(a1 - 24) = *(_DWORD *)(4 * (*(_DWORD *)(a1 - 12) + 1) + a1 - 96);
for ( *(_DWORD *)(a1 - 16) = 0; *(_DWORD *)(a1 - 16) <= 31; ++*(_DWORD *)(a1 - 16) )
{
*(_DWORD *)(a1 - 20) = *(_DWORD *)(a1 - 24) ^ ((*(_DWORD *)(a1 - 20) >> ((*(_BYTE *)(a1 - 24) ^ (*(_BYTE *)(a1 - 12) + *(_BYTE *)(a1 - 16))) & 0xF)) | (*(_DWORD *)(a1 - 20) << (-(char)(*(_BYTE *)(a1 - 24) ^ (*(_BYTE *)(a1 - 12) + *(_BYTE *)(a1 - 16))) & 0xF)));
*(_DWORD *)(a1 - 24) = *(_DWORD *)(a1 - 20) ^ ((*(_DWORD *)(a1 - 24) >> ((*(_BYTE *)(a1 - 20) ^ (*(_BYTE *)(a1 - 12) + *(_BYTE *)(a1 - 16))) & 0xF)) | (*(_DWORD *)(a1 - 24) << (-(char)(*(_BYTE *)(a1 - 20) ^ (*(_BYTE *)(a1 - 12) + *(_BYTE *)(a1 - 16))) & 0xF)));
}
*(_DWORD *)(a1 - 96 + 4 * *(_DWORD *)(a1 - 12)) = *(_DWORD *)(a1 - 20);
*(_DWORD *)(a1 - 96 + 4 * (*(_DWORD *)(a1 - 12) + 1)) = *(_DWORD *)(a1 - 24);
}
return 0;
}
*/

void sub_4018BF(int a1)
{
int i,j;
for ( i = 0; i <= 15; i += 2 )
{
*(_DWORD *)(a1 - 20+96) = *(_DWORD *)(4 * i + a1 - 96+96);//存放第一个数
*(_DWORD *)(a1 - 24+96) = *(_DWORD *)(4 * (i + 1) + a1 - 96+96);
for ( j = 0; j <= 31; ++j )
{

*(_DWORD *)(a1 - 20+96) = *(_DWORD *)(a1 - 24+96) ^ ((*(_DWORD *)(a1 - 20+96) >> ((*(_BYTE *)(a1 - 24+96) ^ (i + j)) & 0xF)) | (*(_DWORD *)(a1 - 20+96) << (32-((char)(*(_BYTE *)(a1 - 24+96) ^ (i + j)) & 0xF))));
*(_DWORD *)(a1 - 24+96) = *(_DWORD *)(a1 - 20+96) ^ ((*(_DWORD *)(a1 - 24+96) >> ((*(_BYTE *)(a1 - 20+96) ^ (i + j)) & 0xF)) | (*(_DWORD *)(a1 - 24+96) << (32-((char)(*(_BYTE *)(a1 - 20+96) ^ (i + j)) & 0xF))));
}
*(_DWORD *)(a1 - 96 + 4 * i+96) = *(_DWORD *)(a1 - 20+96);
*(_DWORD *)(a1 - 96 + 4 * (i + 1)+96) = *(_DWORD *)(a1 - 24+96);
}
return 0;
}

void sub_BF(int a1)
{
int i,j;
for ( i = 0; i <= 15; i += 2 )
{
*(_DWORD *)(a1 - 20+96) = *(_DWORD *)(4 * i + a1 - 96+96);//存放第一个数
*(_DWORD *)(a1 - 24+96) = *(_DWORD *)(4 * (i + 1) + a1 - 96+96);
for ( j = 31; j >= 0; --j )
{
//(*(_DWORD *)(a1 - 24+96) ^ *(_DWORD *)(a1 - 20+96))
*(_DWORD *)(a1 - 24+96) = (((*(_DWORD *)(a1 - 24+96) ^ *(_DWORD *)(a1 - 20+96)) << ((*(_BYTE *)(a1 - 20+96) ^ (i + j)) & 0xF)) | ((*(_DWORD *)(a1 - 24+96) ^ *(_DWORD *)(a1 - 20+96)) >> (32-((char)(*(_BYTE *)(a1 - 20+96) ^ (i + j)) & 0xF))));
*(_DWORD *)(a1 - 20+96) = (((*(_DWORD *)(a1 - 24+96) ^ *(_DWORD *)(a1 - 20+96)) << ((*(_BYTE *)(a1 - 24+96) ^ (i + j)) & 0xF)) | ((*(_DWORD *)(a1 - 24+96) ^ *(_DWORD *)(a1 - 20+96)) >> (32-((char)(*(_BYTE *)(a1 - 24+96) ^ (i + j)) & 0xF))));


}
*(_DWORD *)(a1 - 96 + 4 * i+96) = *(_DWORD *)(a1 - 20+96);
*(_DWORD *)(a1 - 96 + 4 * (i + 1)+96) = *(_DWORD *)(a1 - 24+96);
}
return 0;
}



_BYTE *__cdecl sub_401616(int a1)
{
_BYTE *result; // eax
signed int i; // [esp+Ch] [ebp-10h]

for ( i = 0; i <= 31; ++i )
{
*(_BYTE *)(i + a1) = ~((*(_BYTE *)(i + a1) | byte_405040[i]) & ~(*(_BYTE *)(i + a1) & byte_405040[i]) & ~(i & *(_BYTE *)(i + 32 + a1)) & (i | *(_BYTE *)(i + 32 + a1))) & ((*(_BYTE *)(i + a1) | byte_405040[i]) & ~(*(_BYTE *)(i + a1) & byte_405040[i]) | ~(i & *(_BYTE *)(i + 32 + a1)) & (i | *(_BYTE *)(i + 32 + a1)));
result = (_BYTE *)(i + 32 + a1);
*result = ~((*result | byte_405040[i]) & ~(*result & byte_405040[i]) & ~(i & *(_BYTE *)(i + a1)) & (i | *(_BYTE *)(i + a1))) & ((*result | byte_405040[i]) & ~(*result & byte_405040[i]) | ~(i & *(_BYTE *)(i + a1)) & (i | *(_BYTE *)(i + a1)));
}
return result;
}
_BYTE *__cdecl sub_40(int a1)
{
_BYTE *result; // eax
signed int i; // [esp+Ch] [ebp-10h]

for ( i = 0; i <= 31; ++i )
{
result = (_BYTE *)(i + 32 + a1);
*result = ~((*result | byte_405040[i]) & ~(*result & byte_405040[i]) & ~(i & *(_BYTE *)(i + a1)) & (i | *(_BYTE *)(i + a1))) & ((*result | byte_405040[i]) & ~(*result & byte_405040[i]) | ~(i & *(_BYTE *)(i + a1)) & (i | *(_BYTE *)(i + a1)));

*(_BYTE *)(i + a1) = ~((*(_BYTE *)(i + a1) | byte_405040[i]) & ~(*(_BYTE *)(i + a1) & byte_405040[i]) & ~(i & *(_BYTE *)(i + 32 + a1)) & (i | *(_BYTE *)(i + 32 + a1))) & ((*(_BYTE *)(i + a1) | byte_405040[i]) & ~(*(_BYTE *)(i + a1) & byte_405040[i]) | ~(i & *(_BYTE *)(i + 32 + a1)) & (i | *(_BYTE *)(i + 32 + a1)));

}
return result;
}

unsigned char output[64];
int main()
{
int i;
/*
for(i=0;i<64;i++)//还原顺序
{
output[i] = input[dest[i]];

}
*/
//sub_40(input);解密

sub_40(input);
for(i=0;i<64;i++)//还原顺序
{
output[i] = input[dest[i]];

}
for(i=0;i<64;i++)
input[i] = output[i];
sub_BF(input);
for(i=0;i<64;i++)//还原顺序
{
output[i] = input[dest[i]];

}
for(i=0;i<64;i++)
input[i] = output[i];
for(i=0;i<64;i++)
{
printf("%c",input[i]);

}


return 0;
}

头文件自己加上
X1C{X1cT34m_2@19_N3w_pl4yer}
成功
最后还有一个需求就是反混淆
类似于去花指令

1
2
3
4
5
6
# -*- coding: UTF-8 -*-
data = open('run.exe','rb').read()
data = data.replace('\xE8\x00\x00\x00\x00\x58\x83\xC0\x0A\x50\xE9','\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xE8') #花指令机器码替换为nop
data = data.replace('\xE8\x00\x00\x00\x00\x58\x83\xC0\x0C\x50\xE9','\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\xE8') #花指令机器码替换为nop
data = data.replace('\x58\xFF\xE0','\x90\x90\xC3') #花指令机器码替换为nop
open('run_dejunk.exe','wb').write(data)

效果还是有那么点的
太骑驴

文章目录
|