吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5246|回复: 18
收起左侧

[原创] 010Editor简单算法分析

  [复制链接]
无畏破解 发表于 2019-11-17 12:36
本帖最后由 无畏破解 于 2019-11-17 12:40 编辑

1样本概况
1.1 应用程序信息
应用程序名称:010Editor.exe
MD5值:67399a3650be615df420393758c799cd
SHA1值:95cc3dbfef9781c73d147c44e179edbafac37f42
简单功能介绍:16进制修改、文本修改、模板解析各种文件格式、对比文件
1.2 分析环境及工具           
系统环境:win7 32虚拟机
工具:vs2017、OD、EXEINFOPE、010Editor
1.3 分析目标
010算法分析
2.具体分析过程
2.1 先用ExeinfoPE查看程序的一些基本信息,可以猜出这是用VS2013写的,语言是C++,eax作为返回值,ecx传递this指针。

图片1.png 图片2.png
2.2通过前面信息知道它可能存在重定位,我们先去掉重定位,这样有助于分析。
图片3.png
2.3下面开始破解,找到010Editor的注册界面
图片4.png
2.4输入一个用户名和序列号(随便输),会弹出一个用户名或序列号无效的窗口
图片5.png
2.5现在我们有两种选择,一是根据给出的错误信息,搜索对应的字符串,二是下API断点,栈回溯分析。我们这里先用简单点的字符串搜索试试,如果搜索不到,或者有多处,我们再改用第二种方法
图片6.png
2.6如图,已经搜索到用户名或密码无效的字符串,并且查找下一个没有了,那应该就是我们要找的关键位置了。
图片7.png
2.7双击进入反汇编窗口,分析上下文,在上方找打了疑是注册成功的字符串
图片8.png
2.8继续往上看,找到关键跳转
图片9.png

2.9,到这里我们nop掉跳转,应该就能实现暴力破解了,这次我们要分析算法,所以继续往上跟,我们发现比较cmp edi,0xDB是跳转来的。
图片10.png
2.10转到跳转过来的位置
图片11.png
2.11发现上下两个位置都调用了这个call,更加说明了这是一个关键call,要想注册成功,需要这个call的返回值为0xDB
图片12.png
2.12我们双击进去这个call里进行进一步的分析
图片13.png 图片14.png
2.13在这个call里面我们可以看到有多种返回结果,找到我们要的返回结果0xDB,将光标移动到其上的pop edi,发现是通过跳转到达这里,转到跳转处
图片15.png
2.14跳转的成立的条件是上面最近的一个call的返回值必须为0x2D,所以这也是个关键的call,再次双击进去分析
图片16.png
2.15在这个call里我们发现有三种返回结果,ESI的值,0xE7和0x93,而我们需要返回结果为0x2D,那么就只能让ESI = 0x2D
图片17.png
2.16我们往上看ESI的值是哪来的,发现ESI的值有三种,其中就有我们需要的0x2D
图片18.png
2.17我们将光标移动到mov esi,0x2D处,发现有两处跳转到达这里
图片19.png
2.18我们先跟踪靠上面的一个,要想跳转成立,需要eax<=[EDI+0x1C],而通过分析eax为参数1,而参数1为0x9(常量),
也就是[EDI+0x1C]>=9,则跳转成立
图片20.png
图片21.png
2.19我们先将[EDI+0x1C]的值放一放,我们发现上面要走到这个关键跳转,需要满足几个条件,所以这个函数应该就是我们要找的进行用户名与密码校验的函数,我们从这个函数开始处开始分析。
图片22.png

2.20分析如下,第一个,第二个call分别判断用户名与密码是否为空,第3个call将密码转换为十六进制字节数据,并保存在K[10]字节数组中,后面是对密码的校验,其中K[3]有3种选择,对应三种不同算法,今天我们只分析K[3] = 9C的情况,这种情况其实密码只有16个符号。
图片23.png
图片24.png
2.21,其中有两个关键的函数需要详细的分析,0x00407644处的函数,该函数是对K[0](密码第1个字节)与K[6](第7个字节)进行处理,我们将该函数叫CALL1
图片25.png
2.22 0x004083C8处函数,该函数是对密码K[1]第2,K[7]第8,K[2]第3,K[5]第6个字节进行处理 ,我们将该函数叫CALL2
图片26.png
2.23 CALL1返回值(扩充为4字节后)为EAX1 = ((K[0]^K[6]^0x18+0x3D)^A7)&0xFFESI = (0X100 * (k1 ^ k7 & 0xFF) + k2 ^ k5 & 0xFF) & 0xFFFF;EAX2 = (((ESI ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF
EAX2 % 0xB 为0时,CALL2返回值(扩充为4字节后)为EAX2/0xB
EAX2 % 0xB不为0时,CALL2返回值为0

图片27.png
2.24往下继续分析,如上图,得到CALL1返回值(扩充为4字节)不能为0,CALL2返回值(扩充为4字节)不能为0且<=0x3E8,即EAX1!=0,EAX2 % 0xB==0 &&EAX2 / 0xB <= 0x3E8,让程序按照我们猜想走,会来到我们之前分析的关键跳转处
图片28.png
2.25这里先将用户名转换ascii版,再传入一个加密函数对用户名进行加密,返回一个4字节的数,再将每一个字节与K[10]数组中的一个元素进行对比,看是否一样。我们将返回的4字节的数看成有4个元素的字节数组R[4]的话,K[4]=R[0],K[5]=R[1],K[6]=R[2],K[7]=R[3],接下来就是我们之前分析的[EDI+0x1C]>=9,现在我们往上可以找到[EDI+0x1C]保存的就是我们前面CALL1的返回值(扩充为4字节之后),所以EAX1>=9,那么现在就只剩下用户名加密函数要分析了。
图片29.png
2.26在这里,我们用IDA取个巧,我们先双击进入加密函数,选中第一行,按Ctrl+X复制地址,用IDA将程序打开,按G转到复制出来的地址
图片30.png
图片31.png
2.27然后按F5,然后将代码抠出来直接用,该函数中有个数组,双击看它的地址,再到OD内存数据窗口中找到该地址,将该数组抠出来
直接用。这里注意,该加密函数有四个参数,参数1为需要加密的用户名,参数2为1,参数3为0,参数4为上面的EAX2 / 0xB.
图片32.png
图片33.png
2.28到此我们基本就分析完了一种算法,下面可以根据此算法写个注册机了,下面是完整的注册机代码。
[C++] 纯文本查看 复制代码
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <time.h>


DWORD g_EcodeArray[]={
0x39cb44b8, 0x23754f67, 0x5f017211, 0x3ebb24da, 0x351707c6, 0x63f9774b, 0x17827288, 0x0fe74821, 0x5b5f670f, 0x48315ae8, 0x785b7769, 0x2b7a1547, 0x38d11292, 0x42a11b32, 0x35332244, 0x77437b60,
0x1eab3b10, 0x53810000, 0x1d0212ae, 0x6f0377a8, 0x43c03092, 0x2d3c0a8e, 0x62950cbf, 0x30f06ffa, 0x34f710e0, 0x28f417fb, 0x350d2f95, 0x5a361d5a, 0x15cc060b, 0x0afd13cc, 0x28603bcf, 0x3371066b,
0x30cd14e4, 0x175d3a67, 0x6dd66a13, 0x2d3409f9, 0x581e7b82, 0x76526b99, 0x5c8d5188, 0x2c857971, 0x15f51fc0, 0x68cc0d11, 0x49f55e5c, 0x275e4364, 0x2d1e0dbc, 0x4cee7ce3, 0x32555840, 0x112e2e08,
0x6978065a, 0x72921406, 0x314578e7, 0x175621b7, 0x40771dbf, 0x3fc238d6, 0x4a31128a, 0x2dad036e, 0x41a069d6, 0x25400192, 0x00dd4667, 0x6afc1f4f, 0x571040ce, 0x62fe66df, 0x41db4b3e, 0x3582231f,
0x55f6079a, 0x1ca70644, 0x1b1643d2, 0x3f7228c9, 0x5f141070, 0x3e1474ab, 0x444b256e, 0x537050d9, 0x0f42094b, 0x2fd820e6, 0x778b2e5e, 0x71176d02, 0x7fea7a69, 0x5bb54628, 0x19ba6c71, 0x39763a99,
0x178d54cd, 0x01246e88, 0x3313537e, 0x2b8e2d17, 0x2a3d10be, 0x59d10582, 0x37a163db, 0x30d6489a, 0x6a215c46, 0x0e1c7a76, 0x1fc760e7, 0x79b80c65, 0x27f459b4, 0x799a7326, 0x50ba1782, 0x2a116d5c,
0x63866e1b, 0x3f920e3c, 0x55023490, 0x55b56089, 0x2c391fd1, 0x2f8035c2, 0x64fd2b7a, 0x4ce8759a, 0x518504f0, 0x799501a8, 0x3f5b2cad, 0x38e60160, 0x637641d8, 0x33352a42, 0x51a22c19, 0x085c5851,
0x032917ab, 0x2b770ac7, 0x30ac77b3, 0x2bec1907, 0x035202d0, 0x0fa933d3, 0x61255df3, 0x22ad06bf, 0x58b86971, 0x5fca0de5, 0x700d6456, 0x56a973db, 0x5ab759fd, 0x330e0be2, 0x5b3c0ddd, 0x495d3c60,
0x53bd59a6, 0x4c5e6d91, 0x49d9318d, 0x103d5079, 0x61ce42e3, 0x7ed5121d, 0x14e160ed, 0x212d4ef2, 0x270133f0, 0x62435a96, 0x1fa75e8b, 0x6f092fbe, 0x4a000d49, 0x57ae1c70, 0x004e2477, 0x561e7e72,
0x468c0033, 0x5dcc2402, 0x78507ac6, 0x58af24c7, 0x0df62d34, 0x358a4708, 0x3cfb1e11, 0x2b71451c, 0x77a75295, 0x56890721, 0x0fef75f3, 0x120f24f1, 0x01990ae7, 0x339c4452, 0x27a15b8e, 0x0ba7276d,
0x60dc1b7b, 0x4f4b7f82, 0x67db7007, 0x4f4a57d9, 0x621252e8, 0x20532cfc, 0x6a390306, 0x18800423, 0x19f3778a, 0x462316f0, 0x56ae0937, 0x43c2675c, 0x65ca45fd, 0x0d604ff2, 0x0bfd22cb, 0x3afe643b,
0x3bf67fa6, 0x44623579, 0x184031f8, 0x32174f97, 0x4c6a092a, 0x5fb50261, 0x01650174, 0x33634af1, 0x712d18f4, 0x6e997169, 0x5dab7afe, 0x7c2b2ee8, 0x6edb75b4, 0x5f836fb6, 0x3c2a6dd6, 0x292d05c2,
0x052244db, 0x149a5f4f, 0x5d486540, 0x331d15ea, 0x4f456920, 0x483a699f, 0x3b450f05, 0x3b207c6c, 0x749d70fe, 0x417461f6, 0x62b031f1, 0x2750577b, 0x29131533, 0x588c3808, 0x1aef3456, 0x0f3c00ec,
0x7da74742, 0x4b797a6c, 0x5ebb3287, 0x786558b8, 0x00ed4ff2, 0x6269691e, 0x24a2255f, 0x62c11f7e, 0x2f8a7dcd, 0x643b17fe, 0x778318b8, 0x253b60fe, 0x34bb63a3, 0x5b03214f, 0x5f1571f4, 0x1a316e9f,
0x7acf2704, 0x28896838, 0x18614677, 0x1bf569eb, 0x0ba85ec9, 0x6aca6b46, 0x1e43422a, 0x514d5f0e, 0x413e018c, 0x307626e9, 0x01ed1dfa, 0x49f46f5a, 0x461b642b, 0x7d7007f2, 0x13652657, 0x6b160bc5,
0x65e04849, 0x1f526e1c, 0x5a0251b6, 0x2bd73f69, 0x2dbf7acd, 0x51e63e80, 0x5cf2670f, 0x21cd0a03, 0x5cff0261, 0x33ae061e, 0x3bb6345f, 0x5d814a75, 0x257b5df4, 0x0a5c2c5b, 0x16a45527, 0x16f23945};


int __cdecl EncodeUserName(const char *pszUserName, int a2, char a3, unsigned short a4)
{
	const char *v4; // edx@1
	signed int v5; // esi@1
	signed int v6; // edi@1
	unsigned __int8 v7; // bl@2
	int v8; // eax@3
	int v9; // ecx@3
	int v10; // ecx@4
	int result; // eax@4
	int v12; // ecx@5
	unsigned __int8 v13; // [sp+8h] [bp-10h]@2
	unsigned __int8 v14; // [sp+Ch] [bp-Ch]@2
	unsigned __int8 v15; // [sp+10h] [bp-8h]@2
	int v16; // [sp+14h] [bp-4h]@1

	v4 = pszUserName;
	v16 = 0;
	v5 = strlen(pszUserName);
	v6 = 0;
	if (v5 <= 0)
	{
		result = 0;
	}
	else
	{
		v13 = 0;
		v14 = 0;
		v7 = 15 * a4;
		v15 = 17 * a3;
		do
		{
			v8 = toupper(v4[v6]);
			v9 = v16 + g_EcodeArray[v8];
			if (a2)
			{
				v10 = g_EcodeArray[v7]
					+ g_EcodeArray[v15]
					+ g_EcodeArray[(unsigned __int8)(v8 + 47)] * (g_EcodeArray[(unsigned __int8)(v8 + 13)] ^ v9);
				result = g_EcodeArray[v14] + v10;
				v16 = g_EcodeArray[v14] + v10;
			}
			else
			{
				v12 = g_EcodeArray[v7]
					+ g_EcodeArray[v15]
					+ g_EcodeArray[(unsigned __int8)(v8 + 23)] * (g_EcodeArray[(unsigned __int8)(v8 + 63)] ^ v9);
				result = g_EcodeArray[v13] + v12;
				v16 = g_EcodeArray[v13] + v12;
			}
			v14 += 19;
			++v6;
			v15 += 9;
			v7 += 13;
			v13 += 7;
			v4 = pszUserName;
		} while (v6 < v5);
	}
	return result;
}
int main()
{

	srand(time(NULL));	//设置随机种子
	byte k[10] = { 0x11,0x22,0x33,0x9C,0x55,0x66,0x77,0x88,0x99,0xAA };
	int dwRet =rand()% 0x3E8;
	char szName[100] = { 0 };
	printf("请输入用户名:");
	scanf_s("%s", szName, 100);
	//用户名,加密
	DWORD dwKey = EncodeUserName(szName, 1, 0, dwRet);
	//cmp k[4] ,retValue&0xFF
	//cmp k[5] ,retValue>>8&0xFF
	//cmp k[6] ,retValue>>16&0xFF
	//cmp k[7] ,retValue>>24&0xFF
	k[4] = dwKey & 0xFF;
	k[5] = dwKey >> 8 & 0xFF;
	k[6] = dwKey >> 16 & 0xFF;
	k[7] = dwKey >> 24 & 0xFF;

	//AL = (K[0] ^ K[6] ^ 0X18 + 0X3D) ^ 0XA7
	while (true)
	{
		byte k0 = rand()%0xFF;
		byte k6 = k[6];
		DWORD EAX1 = ((k0^k6 ^ 0x18 + 0x3D) ^ 0xA7) & 0xFF;
		if (EAX1 >= 9)
		{
			k[0] = k0;
			k[6] = k6;
			break;
		}
	}


	//ESI = (0X100*(K[1]^K[7] & 0XFF) + K[2]^K[5] & 0XFF)&0XFFFF
	//EAX = (((ESI^0X7892)+0X4D30)^0X3421)&0XFFFF / 0XB
	//判断余数 是否为0,为0返回商,不为0返回0
	while (true)
	{
		byte k1 = rand() % 0xFF;
		byte k7 = k[7];
		byte k2 = rand() % 0xFF;
		byte k5 = k[5];
		DWORD ESI = (0X100 * (k1 ^ k7 & 0xFF) + k2 ^ k5 & 0xFF) & 0xFFFF;
		DWORD EAX2 = (((ESI ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF;
		if (EAX2 % 0xB ==0 && EAX2 / 0xB == dwRet)
		{
			k[1] = k1;
			k[7] = k7;
			k[2] = k2;
			k[5] = k5;
			break;
		}
	}

	printf("%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X\n", 
		k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8], k[9]);
	system("pause");
	return 0;
}
                          

免费评分

参与人数 7威望 +1 吾爱币 +13 热心值 +5 收起 理由
Hmily + 1 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
柯南帅不帅 + 1 虽然没怎么看太明白,但是感谢分享,慢慢学习一下
幽灵小杰 + 1 为什么和这个一样,https://blog.csdn.net/weixin_44279850/article/detail.
jipiyu + 1 + 1 谢谢@Thanks!
泳诗 + 1 我很赞同!
动物凶猛 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
水木杉 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

动物凶猛 发表于 2019-11-17 13:32
虽然看不懂,但支持
zfzhhh 发表于 2019-11-17 13:42
没有血的江湖 发表于 2019-11-17 13:47
mokson 发表于 2019-11-17 14:21
太高大上,表示看不懂“破文”
驴小毛 发表于 2019-11-17 14:44
很值得学习
jipiyu 发表于 2019-11-17 16:18
谢谢分享,楼主是大好人
earthmingzaizai 发表于 2019-11-18 09:20

虽然看不懂,但支持
柯南帅不帅 发表于 2019-11-18 19:13
虽然没怎么看懂,但是感谢分享,以后慢慢学习一下
pojiexuexi 发表于 2019-11-18 20:48
还是直接修改好...
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-19 02:15

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表