GACTF复现 Easyre wp

这也是一道虚拟机逆向题目:

首先改栈指针(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值