两个关键点
第一个函数先放一放
我把改变后的输入字符串设为 输入2 以示和之前原本输入的字符串有区别
看下第二个点
遍历输入2的每一个字符
和dword的数组对比 每一个都要一样
于是提取下这个数组
ata:0000000000601060 dword_601060 dd 0FFFFFFC4h ; DATA XREF: main+6E↑r
.data:0000000000601064 dd 34h
.data:0000000000601068 dd 22h
.data:000000000060106C dd 0FFFFFFB1h
.data:0000000000601070 dd 0FFFFFFD3h
.data:0000000000601074 dd 11h
.data:0000000000601078 dd 0FFFFFF97h
.data:000000000060107C dd 7
.data:0000000000601080 dd 0FFFFFFDBh
.data:0000000000601084 dd 37h
.data:0000000000601088 dd 0FFFFFFC4h
.data:000000000060108C dd 6
.data:0000000000601090 dd 1Dh
.data:0000000000601094 dd 0FFFFFFFCh
.data:0000000000601098 dd 5Bh
.data:000000000060109C dd 0FFFFFFEDh
.data:00000000006010A0 dd 0FFFFFF98h
.data:00000000006010A4 dd 0FFFFFFDFh
.data:00000000006010A8 dd 0FFFFFF94h
.data:00000000006010AC dd 0FFFFFFD8h
.data:00000000006010B0 dd 0FFFFFFB3h
.data:00000000006010B4 dd 0FFFFFF84h
.data:00000000006010B8 dd 0FFFFFFCCh
.data:00000000006010BC dd 8
注意一下 他不是对比整个dword 他是取了每一个dword的一个字节进行和输入2的每个字符对比。
所以 每一个dword有效的数据其实是最后两个16进制位
如dd 0FFFFFFCCh 有效的是cc
这个数组比较小,其实还是手动转一下快
这个数组可以看成char[] 因为每一个char是一个字节
char dword_arr[]=”\xC4\x34\x22\xB1\xD3\x11\x97\x7\xDB\x37\xC4\x6\x1D\xFC\x5B\xED\x98\xDF\x94\xD8\xB3\x84\xCC\x8”;
由此可以得出在 原始输入的字符串 经过第二个函数变化后 要和这个数组一致;
再来看第一个函数
简单的转换下c代码
__int64 sub_4005B6()
{
unsigned int v0;
__int64 result;
signed int i;
char v3;
for ( i = 0; i <= 14999; i += 3 )
{
v0 = byte_6010C0[i];
v3 = byte_6010C0[i + 2];
result = v0;
switch ( v0 )
{
case 1u:
result = byte_6010C0[i + 1];
input[result]+=v3;
break;
case 2u:
result = byte_6010C0[i + 1];
input[result]-=v3;
break;
case 3u:
result = byte_6010C0[i + 1];
input[result]^=v3;
break;
case 4u:
result = byte_6010C0[i + 1];
input[result]*=v3;
break;
case 5u:
result = byte_6010C0[i + 1];
input[result]^=input[byte_6010C0[i+2]];
break;
default:
continue;
}
}
return result;
}
总结下这个函数
就是取 一个下标值
根据下标值找到输入字符串对应位置 然后把这个位置的数据 根据case的条件±*/异或
就是改变了输入字符串 最后的结果就是 这样
char dword_arr[]=”\xC4\x34\x22\xB1\xD3\x11\x97\x7\xDB\x37\xC4\x6\x1D\xFC\x5B\xED\x98\xDF\x94\xD8\xB3\x84\xCC\x8”;
byte_6010C0数组依然是直接读取文件就可以得到。
注意 在这函数里 的条件±*/都要反一下才是逆过去
而且
逆过去的时候 数组不再是从0开始
而是从最后那个开始
14999/3 最大的下标取到14997
所以最后这个函数可以变成
__int64 sub_4005B6(char* input,char *byte_6010C0)
{
unsigned int v0;
__int64 result;
signed int i;
char v3;
for (i = 14997; i >=0; i -= 3)
{
v0 = byte_6010C0[i];
v3 = byte_6010C0[i + 2];
result = v0;
switch (v0)
{
case 1u:
result = byte_6010C0[i + 1];
input[result] -= v3;
break;
case 2u:
result = byte_6010C0[i + 1];
input[result] += v3;
break;
case 3u:
result = byte_6010C0[i + 1];
input[result] ^= v3;
break;
case 4u:
result = byte_6010C0[i + 1];
input[result] /= v3;
break;
case 5u:
result = byte_6010C0[i + 1];
input[result] ^= input[byte_6010C0[i + 2]];
break;
default:
continue;
}
}
return result;
}
代入
char dword_arr[]=”\xC4\x34\x22\xB1\xD3\x11\x97\x7\xDB\x37\xC4\x6\x1D\xFC\x5B\xED\x98\xDF\x94\xD8\xB3\x84\xCC\x8”;
byte_6010C0数组
即可得到原始的input
解题代码
// ConsoleApplication9.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
#include
using namespace std;
char dword_arr[] = "\xC4\x34\x22\xB1\xD3\x11\x97\x7\xDB\x37\xC4\x6\x1D\xFC\x5B\xED\x98\xDF\x94\xD8\xB3\x84\xCC\x8";
__int64 sub_4005B6(char* input,char *byte_6010C0)
{
unsigned int v0;
__int64 result;
signed int i;
char v3;
for (i = 14997; i >=0; i -= 3)
{
v0 = byte_6010C0[i];
v3 = byte_6010C0[i + 2];
result = v0;
switch (v0)
{
case 1u:
result = byte_6010C0[i + 1];
input[result] -= v3;
break;
case 2u:
result = byte_6010C0[i + 1];
input[result] += v3;
break;
case 3u:
result = byte_6010C0[i + 1];
input[result] ^= v3;
break;
case 4u:
result = byte_6010C0[i + 1];
input[result] /= v3;
break;
case 5u:
result = byte_6010C0[i + 1];
input[result] ^= input[byte_6010C0[i + 2]];
break;
default:
continue;
}
}
return result;
}
int main()
{
HANDLE hFile = CreateFile(L"F:/WxyVM1", GENERIC_ALL, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==NULL) { cout << "打开文件出错" << endl; return 1; }
char buf[0x10c0] = { 0 };
DWORD bufLen = 0x10c0;
DWORD RealReadLen = 0;
bool res=ReadFile(hFile, buf, bufLen, &RealReadLen, NULL);
if (!res) { cout << "读文件出错" << endl; return 1; }
char byte_6010C0[15000] = { 0 };
bufLen = 15000;
res = ReadFile(hFile, byte_6010C0, bufLen, &RealReadLen, NULL);
if (bufLen!=15000) { cout << "读文件出错" << endl; return 1;}
sub_4005B6(dword_arr, byte_6010C0);
cout << dword_arr << endl;
return 0;
}