脑洞题,直接没说法,就以后别碰这种脑洞题就行,,,,没任何帮助
看到上方输出框有字符串,所以我们来查找字符串ctrl+F12
好熟悉的东西,但就是最后一个没有输出。盲猜是flag,然后根据交叉引用
去找源地址。
找到了地址是0x4013ED
,把它放入edx
伪代码是这个东西,啥也看不到,动用OD吧,动调一下
拖动进去之后,直接ctrl +G 输入地址0x4013ED
,然后下个断点,
不断地F8
之后,到达函数末端时,再回关键点看看
flag:aliens_are_around_us
首先呢,它属于加了upx
壳的,需要用脱壳工具处理一下,然后直接找到核心伪代码,进行爆破。。
byte_402150
和 byte_402151
,其实它俩都是同一个数组,只是找偏移的时候在[ ]里面多加1就行,一个while循环作用
byte_402150
数组和byte_4021A0
的长度不一样,而且其中一个数组的长度挺长的,所以直接用个无限循环,直到赋值完之后直接break即可接下来上数组:
byte_402150
好家伙,这是一个字符数组,然后呢,该怎么找出来呢?
简单,直接找hex View-1
找准起始位置,找准结束位置,把16进制数据,全部拷贝出来,然后依次加上0x
,说实话,把我手都加麻了。。。。我在这里直接拷贝出来给你们吧,否则你们也会麻。。。
0x32,0x61, 0x34, 0x39, 0x66, 0x36, 0x39, 0x63, 0x33, 0x38, 0x33,0x39,0x35,
0x63, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36,
0x66,0x34,0x65, 0x30, 0x32, 0x35, 0x34, 0x38, 0x34, 0x39, 0x35, 0x34, 0x64,
0x36, 0x31, 0x39, 0x35,0x34,0x34, 0x38,0x64, 0x65, 0x66, 0x36, 0x65, 0x32,
0x64, 0x61, 0x64, 0x36, 0x37, 0x37, 0x38,0x36,0x65, 0x32, 0x31, 0x64, 0x35,
0x61, 0x64, 0x61, 0x65, 0x36, 0x00
接下来上数组:
byte_4021A0
找出方法一样的,
往下看,一眼望不到边。。难不成我们得一个一个慢慢复制?不可能,直接hex窗口
把它们拷贝出来之后,加上0x
,说实话,把我手都加麻了。。。。我在这里直接拷贝出来给你们吧,否则你们也会麻。。。
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE,
0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4,
0xA2, 0xAF,0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7,
0xCC, 0x34, 0xA5, 0xE5, 0xF1,0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3,
0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,0xEB, 0x27, 0xB2, 0x75, 0x09,
0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3,0x29,
0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A,
0xCB, 0xBE, 0x39,0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43,
0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3,
0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21,0x10, 0xFF,
0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7,
0x7E, 0x3D,0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A,
0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A,
0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62,0x91, 0x95, 0xE4,
0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4,
0xEA,0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4,
0xC6, 0xE8, 0xDD, 0x74, 0x1F,0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5,
0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,0x86, 0xC1, 0x1D,
0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87,
0xE9,0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42,
0x68, 0x41, 0x99, 0x2D, 0x0F,0xB0, 0x54, 0xBB, 0x16
这里呢,强调一下v4+v2
。这里v4
是一个偏移,v2
是我们输入字符的起始地址,然后这个地址大小是 一个字节,(signed int)*
后面这一字节的地址值又被强制转换成有符号型的数据,即-128~127,根据前面所知,这里依然是一个地址偏移,
所以直接0~127(即我们输入的值),又因为此时不知道,所以我们只能通过循环找出
提示一下,这里是byte_4021A0[16 * (((signed int)*(_BYTE *)(v4 + v2) >> 4) % 16)]
相当于a[i],但是前面还有一个&
,此时又被变成一个地址值,然后加后面的 (16 * *(_BYTE *)(v4 + v2) >> 4) % 16)
,道理同前面一样。
实现代码
#include
using namespace std;
int main()
{
int a[] = {
0x32,0x61, 0x34, 0x39, 0x66, 0x36, 0x39, 0x63, 0x33, 0x38, 0x33,
0x39,0x35, 0x63, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36, 0x64, 0x65, 0x39, 0x36, 0x64, 0x36, 0x66,
0x34,0x65, 0x30, 0x32, 0x35, 0x34, 0x38, 0x34, 0x39, 0x35, 0x34, 0x64, 0x36, 0x31, 0x39, 0x35,
0x34,0x34, 0x38,0x64, 0x65, 0x66, 0x36, 0x65, 0x32, 0x64, 0x61, 0x64, 0x36, 0x37, 0x37, 0x38,
0x36,0x65, 0x32, 0x31, 0x64, 0x35, 0x61, 0x64, 0x61, 0x65, 0x36, 0x00 };
int b[] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF,
0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1,
0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3,
0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39,
0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21,
0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D,
0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62,
0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA,
0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9,
0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
0xB0, 0x54, 0xBB, 0x16 };
char flag[35];
int v6, v9, v8;
int i = 0;
int k = 0;
int a1;
while (1) {
if (a[2 * i] < 48 || a[2 * i] >57)
v6 = a[2 * i] - 87;
else
v6 = a[2 * i] - 48;
v8 = 16 * v6;
if (a[2 * i + 1] < 48 || a[2 * i + 1] >57)
v9 = a[2 * i + 1] - 87;
else
v9 = a[2 * i + 1] - 48;
for (int j = 0; j<127; j++) {
a1 = (j >> 4) % 16;
if (((v8 + v9) ^ 0x19) == b[16 * a1 + ((16 * j >> 4) % 16)])
{
flag[k] = char(j);
cout << flag[k];
k++;
break;
}
}
i += 1;
if (i >= 35)
break;
}
}
if (((v8 + v9) ^ 0x19) == b[16 * a1 + ((16 * j >> 4) % 16)])
这行代码绝对不能写成
if ((v8 + v9) ^ 0x19 == b[16 * a1 + ((16 * j >> 4) % 16)])
这样,必须用括号把左边括起来,因为运算符优先级原因。。
没加括号的我,一直在这里if直接一直成立!!!!!!!!输出了个寂寞!!!折腾了两个小时,就为了个括号!!!!!!!!!!!!一生耻辱!!写出逆向代码的时间还没找括号时间一半多。。。。。