跳转至

【RE】32位调用64位exe程序

32位调用64位exe程序

在x64系统下,程序一般分为32位和64位程序,但是32位程序可以调用64位的代码,32位模式的时候,CS=0x23,64位的时候CS=0x33,如果要切换这两种模式,就需要汇编指令retf,所以32位程序调用64位代码的特征为0x33和retf,当存在这种情况时,不能正常识别成代码,只有16进制的数或者汇编,静态和动调都会不好弄,现在来做一个题目

image-20211219155547622

查看sub_402420函数处的汇编,发现了retf和0x33,所以在这里调用了64位的程序,所以下面没有正确识别

image-20211219155605382

010把它改成64的程序,试图---模板结果,找到程序的信息

image-20211219161253022

然后再给他改成64位

image-20211219165638883

修改之后,程序就变成了64位,就可以识别代码了,但是刚打开还是比较乱

image-20211219170335907

rebase,把基址改成和原来程序一样的基址,然后定位到retf下面那里,可以看到,和原来的402176的内容是一样的

image-20211219181355253

image-20211219181441862

然后重新定义,就得到了加密的逻辑

image-20211219182203253

image-20211219182212340

是一个魔改xxtea

下一步,就是寻找enc,在原来的程序中比较好找,其实就是unk_42771C

image-20211219191238391

查看sub_402480函数,正好是4个一组

image-20211219191331939

得到加密后的值

0xF5, 0x58, 0xF7, 0xD8, 0xDB, 0x49, 0x68, 0x52, 0x63, 0x25, 
0xD7, 0xE2, 0xAC, 0xEF, 0x5E, 0x48, 0xC6, 0x4B, 0x8F, 0x60, 
0x6A, 0xF7, 0x59, 0x58, 0xA3, 0x65, 0x35, 0xB0, 0xC1, 0x91, 
0x40, 0x3E, 0x9A, 0x5B, 0xDB, 0xD3

最后写出解密脚本

#include <stdio.h>
#include <stdint.h>
#include<iostream>
using namespace std;
void decrypt(unsigned int *v) 
{
  unsigned int z;
  unsigned int sum; 
    unsigned int e; 
    int i;
    unsigned int y; 
  uint32_t k[4] = {0xEFCDAB89, 0x10325476, 0x98BADCFE, 0xC3D2E1F0};
    y = v[0];
    sum = 0xD73DA40C;
    do
    {
        for ( i = 8; i > 0; --i )
        {
            e = (sum >> 2) & 3;
            z = v[i - 1];
            y = v[i] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
        }
        z = v[8];
        y = v[0] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
        sum -= 0x67452301;
    }
    while (sum != 0 );
}



int main() {
    uint32_t v[9] = {
            0xD8F758F5, 0x526849DB, 0xE2D72563, 0x485EEFAC, 0x608F4BC6, 0x5859F76A, 0xB03565A3, 0x3E4091C1,
            0xD3DB5B9A
    };
    decrypt(v);

    printf("%s",v);

    return 0;
}

flag

flag{529e3d91db48e084f76fca97b94499}