逆向WxyVM1----给同学写的解题思路

给同学写的,上传下当做笔记
在这里插入图片描述

两个关键点

第一个函数的作用是改变输入的字符串
在这里插入图片描述

第一个函数先放一放
我把改变后的输入字符串设为 输入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 <iostream>
#include <windows.h>
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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值