这也是一道虚拟机逆向题目:
首先改栈指针(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/108312602https://www.52pojie.cn/thread-1258424-1-1.html#33922724_re