这也是一道虚拟机逆向题目:
首先改栈指针(alt+k),f5反编译主函数:
sub_8048DE2()可以看出这是一个虚拟机:
&unk_804B080找到opcode:
从主函数可以看到,在执行sub_8048838前,调用了前一个函数,对它进行动态patch
(直接点进去sub_8048838会发现是无意义代码)
反编译后的sub_8048838():
int __cdecl sub_8048838(_DWORD *a1)
{
int v1; // ecx
_BYTE *v2; // ST28_4
int result; // eax
unsigned int v4; // et1
unsigned int v5; // [esp+2Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
while ( 1 )
{
if ( *(_BYTE *)a1[8] == 113 ) // 没用到
{
a1[6] -= 4;
*(_DWORD *)a1[6] = *(_DWORD *)(a1[8] + 1);
a1[8] += 5;
}
if ( *(_BYTE *)a1[8] == 65 ) // a1[1] += a1[2]
{
a1[1] += a1[2];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 66 ) // a1[1] -= a1[4]
{
a1[1] -= a1[4];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 67 ) // a1[1] *= a1[3]
{
a1[1] *= a1[3];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 68 ) // a1[1] /= a1[5]
{
a1[1] /= a1[5];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 128 ) // op ? (int)num a1[9] = num opn += 6
{
a1[return_a1_add_32_add_1((int)a1, 1u)] = *(_DWORD *)(a1[8] + 2);
a1[8] += 6;
}
if ( *(_BYTE *)a1[8] == 119 ) // a1[1] ^= a1[9]
{
a1[1] ^= a1[9];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 83 ) // 没用到
{
sub_80485F0(*(char *)a1[3]);
a1[8] += 2;
}
if ( *(_BYTE *)a1[8] == 34 ) // a1[1] >>= a1[2]
{
v1 = a1[2];
a1[1] >>= v1;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 35 ) // a1[1] <<= a1[2]
{
v1 = a1[2];
a1[1] <<= v1;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 153 ) // 跳出循环
break;
if ( *(_BYTE *)a1[8] == 118 ) // 没用到
{
a1[3] = *(_DWORD *)a1[6];
*(_DWORD *)a1[6] = 0;
a1[6] += 4;
a1[8] += 5;
}
if ( *(_BYTE *)a1[8] == 84 ) // 没用到
{
v2 = (_BYTE *)a1[3];
*v2 = sub_8048580();
a1[8] += 2;
}
if ( *(_BYTE *)a1[8] == 48 ) // a1[1] |= a1[2]
{
a1[1] |= a1[2];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 49 ) // a1[1] &= a1[2]
{
a1[1] &= a1[2];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 9 ) //a1[1] = 输入int64
{
a1[1] = dword_804B28C;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 16 ) // a1[9] = a1[1]
{
a1[9] = a1[1];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 17 ) // printf("%p\n", a1[1])
{
printf((const char *)&unk_804920C, a1[1]);
++a1[8];
}
if ( *(_BYTE *)a1[8] == 160 ) // if (a1[1] == 0x26F8D100) opn++ else exit()
{
if ( a1[1] == 653840640 )
++a1[8];
else
exit();
}
if ( *(_BYTE *)a1[8] == 161 ) // 输入flag, flag = byte_804B2E0
{
printf("flag:");
sub_8048560(0, (int)byte_804B2E0, 40);
if ( strlen((int)byte_804B2E0) != 33 )
exit();
++a1[8];
}
if ( *(_BYTE *)a1[8] == 177 ) // a1[9] = dword_804B2A0[0]
{
a1[9] = dword_804B2A0[0];
++a1[8];
}
if ( *(_BYTE *)a1[8] == 178 ) // a1[9] = dword_804B2A4
{
a1[9] = dword_804B2A4;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 164 ) // op byte(num) ? ? dword_804B2A0[num] = a1[1] opn += 4(后两字节无效)
{
dword_804B2A0[*(unsigned __int8 *)(a1[8] + 1)] = a1[1];
a1[8] += 4;
}
if ( *(_BYTE *)a1[8] == 179 ) // a1[9] = dword_804B2A8
{
a1[9] = dword_804B2A8;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 180 ) // a1[9] = dword_804B2AC
{
a1[9] = dword_804B2AC;
++a1[8];
}
if ( *(_BYTE *)a1[8] == 193 ) // op byte(num) a1[1] = byte_804B2E0[num] opn += 2
{
a1[1] = byte_804B2E0[*(unsigned __int8 *)(a1[8] + 1)];
a1[8] += 2;
}
if ( *(_BYTE *)a1[8] == 194 ) // op (int)num if (a1[1] == num) opn += 5
{
if ( a1[1] != *(_DWORD *)(a1[8] + 1) )
exit();
a1[8] += 5;
}
}
v4 = __readgsdword(0x14u);
result = v4 ^ v5;
if ( v4 != v5 )
result = sub_8048590(v1);
return result;
用下面的脚本来分析opcode:
dic = [
(65, 'a1[1] += a1[2]', 1),
(66, 'a1[1] -= a1[4]', 1),
(67, 'a1[1] *= a1[3]', 1),
(68, 'a1[1] /= a1[5]', 1),
(128, 'a1[?] = %d', 6),
(119, 'a1[1] ^= a1[9]', 1),
(34, 'a1[1] >>= a1[2]', 1),
(35, 'a1[1] <<= a1[2]', 1),
(153, '跳出循环', 1),
(48, 'a1[1] |= a1[2]', 1),
(49, 'a1[1] &= a1[2]', 1),
(9, 'a1[1] = 输入int', 1),
(16, 'a1[9] = a1[1]', 1),
(17, 'printf("%p\n", a1[1])', 1),
(160, 'if (a1[1] == 0x26F8D100) opn++ else exit()', 1),
(161, '输入flag, flag = byte_804B2E0', 1),
(177, 'a1[9] = dword_804B2A0[0]', 1),
(178, 'a1[9] = dword_804B2A4', 1),
(164, 'dword_804B2A0[%d] = a1[1]', 4),
(179, 'a1[9] = dword_804B2A8', 1),
(180, 'a1[9] = dword_804B2AC', 1),
(193, 'a1[1] = byte_804B2E0[%d]', 2),
(194, 'if (a1[1] == %d)', 5)
]
def get_int(b):
import struct
return struct.unpack('I', b)[0]
with open('dump', 'rb')as f:
b = f.read()
opn = 0
while (True):
op = b[opn]
for i in range(len(dic)):
if op == dic[i][0]:
code = dic[i][1]
if op == 128:
num = get_int(b[opn+2:opn+2+4])
print(code % num)
elif op == 164 or op == 193:
num = b[opn+1]
print(code % num)
elif op == 194:
num = get_int(b[opn+1:opn+1+4])
print(code % num)
else:
print(code)
opn += dic[i][2]
break
输出伪代码:
a1[1] = 输入int
a1[9] = a1[1]
a1[2] = 13
a1[1] >>= a1[2]
a1[1] ^= a1[9] //a1[1] = a1[1] ^ (a1[1] >> 13)
a1[9] = a1[1] //a1[9] = a1[1]
a1[2] = 9
a1[1] <<= a1[2]
a1[2] = 2029229568
a1[1] &= a1[2]
a1[1] ^= a1[9] //a1[1] = ((a1[1] << 9) & 0x78f39600) ^ a1[1]
a1[9] = a1[1] //a1[9] = a1[1]
a1[2] = 17
a1[1] <<= a1[2]
a1[2] = 2245263360
a1[1] &= a1[2]
a1[1] ^= a1[9] //a1[1] = ((a1[1] << 17) & 0x85d40000) ^ a1[1]
a1[9] = a1[1] //a1[9] = a1[1]
a1[2] = 19
a1[1] >>= a1[2]
a1[1] ^= a1[9] //a1[1] = (a1[1] >> 19) ^ a1[1]
if (a1[1] == 0x26F8D100) opn++ else exit()
a1[1] = 输入int
a1[?] = 255
a1[1] &= a1[2]
a1[?] = 2
a1[1] *= a1[3]
a1[?] = 24
a1[1] += a1[2]
dword_804B2A0[0] = a1[1] // (a1[1] & 255) * 2 + 24
a1[1] = 输入int
a1[?] = 8
a1[1] >>= a1[2]
a1[?] = 255
a1[1] &= a1[2]
a1[?] = 7
a1[1] /= a1[5]
a1[?] = 33
a1[1] += a1[2]
dword_804B2A0[1] = a1[1] // ((a1[1] >> 8) & 255) / 7 + 33
a1[1] = 输入int
a1[?] = 16
a1[1] >>= a1[2]
a1[?] = 255
a1[1] &= a1[2]
a1[?] = 187
a1[1] ^= a1[9]
a1[?] = 255
a1[1] += a1[2]
dword_804B2A0[2] = a1[1] // (((a1[1] >> 16) & 255) ^ 187) + 255
a1[1] = 输入int
a1[?] = 24
a1[1] >>= a1[2]
a1[?] = 255
a1[1] &= a1[2]
a1[?] = 160
a1[1] -= a1[4]
a1[?] = 119
a1[1] += a1[2]
dword_804B2A0[3] = a1[1] // ((a1[1] >> 24) & 255) - 160 + 119
输入flag, flag = byte_804B2E0
a1[1] = byte_804B2E0[0]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 267) // if (flag[i] ^ dword_804B2A0[0] == 267)
a1[1] = byte_804B2E0[1]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 122) // if (flag[i] ^ dword_804B2A0[1] == 122)
a1[1] = byte_804B2E0[2]
a1[9] = dword_804B2AC
a1[1] ^= a1[9]
if (a1[1] == 149) // if (flag[i] ^ dword_804B2A0[3] == 149)
a1[1] = byte_804B2E0[3]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 262) // if (flag[i] ^ dword_804B2A0[2] == 262)
a1[1] = byte_804B2E0[4]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 125) // if (flag[i] ^ dword_804B2A0[1] == 125)
a1[1] = byte_804B2E0[5]
a1[9] = dword_804B2AC
a1[1] ^= a1[9]
if (a1[1] == 173)
a1[1] = byte_804B2E0[6]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 303)
a1[1] = byte_804B2E0[7]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 357)
a1[1] = byte_804B2E0[8]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 301)
a1[1] = byte_804B2E0[9]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 303)
a1[1] = byte_804B2E0[10]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 313)
a1[1] = byte_804B2E0[11]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 269)
a1[1] = byte_804B2E0[12]
a1[9] = dword_804B2AC
a1[1] ^= a1[9]
if (a1[1] == 187)
a1[1] = byte_804B2E0[13]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 8)
a1[1] = byte_804B2E0[14]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 269)
a1[1] = byte_804B2E0[15]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 319)
a1[1] = byte_804B2E0[16]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 314)
a1[1] = byte_804B2E0[17]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 353)
a1[1] = byte_804B2E0[18]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 87)
a1[1] = byte_804B2E0[19]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 288)
a1[1] = byte_804B2E0[20]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 269)
a1[1] = byte_804B2E0[21]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 319)
a1[1] = byte_804B2E0[22]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 319)
a1[1] = byte_804B2E0[23]
a1[9] = dword_804B2AC
a1[1] ^= a1[9]
if (a1[1] == 181)
a1[1] = byte_804B2E0[24]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 275)
a1[1] = byte_804B2E0[25]
a1[9] = dword_804B2AC
a1[1] ^= a1[9]
if (a1[1] == 160)
a1[1] = byte_804B2E0[26]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 289)
a1[1] = byte_804B2E0[27]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 269)
a1[1] = byte_804B2E0[28]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 11)
a1[1] = byte_804B2E0[29]
a1[9] = dword_804B2A8
a1[1] ^= a1[9]
if (a1[1] == 313)
a1[1] = byte_804B2E0[30]
a1[9] = dword_804B2A0[0]
a1[1] ^= a1[9]
if (a1[1] == 371)
a1[1] = byte_804B2E0[31]
a1[9] = dword_804B2A4
a1[1] ^= a1[9]
if (a1[1] == 70)
跳出循环
(其实知道flag格式为GACTF{XXXXX},所以其实前四个数可以不用去逆出来,直接试就好了...不过因为是赛后复现学习,还是尽量详细了qaq)
最终exp(c++版本):
int main()
{
cout << char(11 + 256 ^ 332);
cout << char(122 ^ 59);
cout << char(149 ^ 214);
cout << char(6 + 256 ^ 338);
cout << char(125 ^ 59);
cout << char(173 ^ 214);
cout << char(47 + 256 ^ 332);
cout << char(101 + 256 ^ 338);
cout << char(45 + 256 ^ 332);
cout << char(47 + 256 ^ 332);
cout << char(57 + 256 ^ 338);
cout << char(13 + 256 ^ 338);
cout << char(187 ^ 214);
cout << char(8 ^ 59);
cout << char(13 + 256 ^ 338);
cout << char(63 + 256 ^ 332);
cout << char(58 + 256 ^ 338);
cout << char(97 + 256 ^ 338);
cout << char(87 ^ 59);
cout << char(32 + 256 ^ 332);
cout << char(13 + 256 ^ 338);
cout << char(63 + 256 ^ 332);
cout << char(63 + 256 ^ 338);
cout << char(181 ^ 214);
cout << char(19 + 256 ^ 332);
cout << char(160 ^ 214);
cout << char(33 + 256 ^ 332);
cout << char(13 + 256 ^ 338);
cout << char(11 ^ 59);
cout << char(57 + 256 ^ 338);
cout << char(115 + 256 ^ 332);
cout << char(70 ^ 59);
}
最终exp(python版本):
a = 4293442714
a = 0xffe8bc9a
l = [0] * 4
l[0] = (a & 255) * 2 + 24
l[1] = ((a >> 8) & 255) // 7 + 33
l[2] = (((a >> 16) & 255) ^ 187) + 255
l[3] = ((a >> 24) & 255) - 160 + 119
print(l)
flag = [0] * 32
flag[0] = l[0] ^ 267
flag[1] = l[1] ^ 122
flag[2] = l[3] ^ 149
flag[3] = l[2] ^ 262
flag[4] = l[1] ^ 125
flag[5] = l[3] ^ 173
flag[6] = l[0] ^ 303
flag[7] = l[2] ^ 357
flag[8] = l[0] ^ 301
flag[9] = l[0] ^ 303
flag[10] = l[2] ^ 313
flag[11] = l[2] ^ 269
flag[12] = l[3] ^ 187
flag[13] = l[1] ^ 8
flag[14] = l[2] ^ 269
flag[15] = l[0] ^ 319
flag[16] = l[2] ^ 314
flag[17] = l[2] ^ 353
flag[18] = l[1] ^ 87
flag[19] = l[0] ^ 288
flag[20] = l[2] ^ 269
flag[21] = l[0] ^ 319
flag[22] = l[2] ^ 319
flag[23] = l[3] ^ 181
flag[24] = l[0] ^ 275
flag[25] = l[3] ^ 160
flag[26] = l[0] ^ 289
flag[27] = l[2] ^ 269
flag[28] = l[1] ^ 11
flag[29] = l[2] ^ 313
flag[30] = l[0] ^ 371
flag[31] = l[1] ^ 70
print(flag)
print(''.join(map(chr, flag)))
参考链接:
https://blog.csdn.net/tqydyqt/article/details/108312602
https://www.52pojie.cn/thread-1258424-1-1.html#33922724_re