ブラスト010EditorとRI

神ナインヤンの道議会より転載

免責事項:この記事は再現CC BY-SA 4.0の著作権契約を、従って、ブロガーオリジナル記事です、元のソースのリンクと、この文を添付してください。

このリンク:https://blog.csdn.net/qq_31507523/article/details/90083813

010Editorとフィルモアが用意されて爆発をリバース

実験プラットフォーム:win10 64魏

実験ツール:OD、VS2017

非常に強力な16進編集ツールの010Editor、編集するテキストファイル、XML、HTML、UnicodeとUTF-8のファイル、C / C +のソースコード、PEファイルのサポート。ユニバーサル感などのようにそれを使用することに慣れ... 010エディタなぜ強いですか?唯一の違いは、ファイルの伝統的なバイナリエディタの生のバイトの16進数で表示され、エディタ010はまた、バイナリテンプレート階層にファイルを解析するために使用することができます。唯一の生の進バイトを使用するよりも理解しやすいと編集バイナリテンプレートの実行結果。

まず、ブルートフォース

まず、スタート後にインストール登録画面を見つけ、インストールパッケージの9.0バージョンを取得、ちょうどあなたのユーザー名とパスワードを入力すると、ダイアログボックスを登録すると、登録が失敗したプロンプトをクリックした後に表示されます。コピーしたテキストファイルを作成し、箱の中に入ることができ、文字列の内容を貼り付け]ダイアログボックスのCtrl + Cを指すことができます。

1565953445207

使い方はOD、分析プレスもしくはCtrl + Aの下で、検索文字列「無効な名またはパスワード...」逆アセンブルコード列にダブルクリックが存在するプログラム、モジュールを開き、文字列情報の近くにそれを見、英語以上のことを言って分析モジュールは右、あなたがジャンプのアドレスを見ることができる上に、メモリ・ウィンドウの左端の列のHEXデータにジャンプするように表示され、矢印案内します後の意味が、パスワードの有効期限が切れて受け入れられ、それは、我々が望むものは確かではありません過去にジャンプします。

1565953456278

文字列は、我々はジャンプの後の最初のポイントでどのプログラムがわからない、使用目的に近いジャンプが拡張された後に、これは私たちが望むものではありません、その後、ビューの更なるポイントは2つのジャンプ(矢印のヒントとHEXバー)がありますがありますその後、最初にプログラムするF9と実行しているが、これら2つのアドレスがブレークポイントである後に、その名前とパスワードを入力し、最初の2つのブレークポイントに彼をサインオフ]をクリックし、あなたがこれを確認することができ、我々が分析する必要があり、その後でそれはジャンプポイントアップの左下隅にジャンプします。

1565953469404

跳转之后查看附近代码的字符串,发现下面有一行英文,翻译过来就是许可证已授权,说明019282A6 地址就是一个关键跳转。

1565953481571

那么现在就把019282A6地址的这一行代码NOP掉,打一个补丁,查看破解是否成功,确实破解成功了,但是每次重启010Editor的时候都需要重新点击注册,这很繁琐,并没有达到完美破解。

1565953497307

那么继续分析之前代码,关键条上一行对比了EDI应该为0xDB,发现有两个位置都跳转到这条代码,通过观察这2个地址相距很近,那随便选一个先跳上去。 然后发现上面有个函数CALL,EDI的值的EAX赋予的,那么可以得出这个CALL就是一个关键函数。

1565953530452

那么进入关键函数,先观察原来retn 的值是多少,然后直接在函数内第一行修改返回值,之后打个补丁。

1565953540275

启动破解后的补丁程序,就发现,重启不需要重新注册,完美破解了,查看一下注册信息,正是我们之前的用户名许可了。

1565953549019

二、注册机编写

暴破的时候已经找到了关键函数。进入函数分析内部代码,需要逆向分析,从最后的返回值为0xDB,从下往上看需要满足的条件,最终发现返回值为0xDB必要是有一个关键函数2的返回值为0x2D,那么接下来分析这个函数即可。

1565953565028

进入关键函数2后,大概分析了下,很长,涉及到一些算法计算,那么久要做好单步跟踪的准备了,那么久单步跟踪吧,只要是有计算的代码全都写上注释,逆向时好记性不如烂笔头。分析算法片段图:

1565953577980

慢慢分析,没啥技巧可言,就是单步跟踪,我分析了一整天后终于写出了注册机:

#include "pch.h"
#include <iostream>
#include <windows.h>
#include <ctime>
#include <locale>
#include <ctype.h>


//生成Hash值算法时所用到的一个4字节数组
int ARR[] = {
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 };


//利用用户名生成一个Hash值的算法
int CreateHash(const char* userName, int ARG2, int ARG3, int ARG4)
{
//定义4个局部变量
int LOC1, LOC2, LOC3, LOC4;
LOC1 = LOC2 = LOC3 = LOC4 = 0;
//用户名的长度
int userLengh = strlen(userName);
if (!userName)
{
printf("用户名长度为0了");
getchar();
exit(0);
}
LOC2 = (ARG3 << 4) + ARG3;

for (size_t i = 0; i < userLengh; i++)
{
//取出每个字节
char ASC = *userName;
//转大写
ASC = toupper(ASC);

static int EBX = (ARG4 << 4) - ARG4;

if (ARG2!=0)//==1
{
int Temp1, Temp2, Temp3;
Temp1 = (ARR[ASC] + LOC1)^(ARR[(ASC + 0xD) & 0xFF]);
Temp2 = Temp1 * ARR[(ASC + 0x2F) & 0xFF] + ARR[LOC2 & 0xFF];
Temp3 = (Temp2 + ARR[EBX & 0xFF]) + ARR[LOC3 & 0xFF];
LOC1 = Temp3;
}
else//==0
{
int Temp4, Temp5, Temp6;
Temp4 = (ARR[ASC] + LOC1) ^ ARR[(ASC + 0x3F) & 0xFF];
Temp5 = Temp4 * ARR[(ASC + 0x17) & 0xFF] + ARR[LOC2 & 0xFF];
Temp6 = (Temp5 + ARR[EBX & 0xFF]) + ARR[LOC4 & 0xFF];
LOC1 = Temp6;
}
LOC3 += 0x13;
LOC2 += 0x9;
LOC4 += 0x7;
EBX += 0xD;
//下一个字节
userName++;
}
return LOC1;
}


int main()
{
//设置随机因子
srand((unsigned int)time(NULL));

printf("请输入用户名:");
char Name[50] = {};
scanf_s("%s", Name, 50);

//密钥数组
byte K[10] = {};
//第3个字节设为9C
K[3] = 0x9C;
//通过一个Hash值计算出4,5,6,7字节的数字
DWORD VALUE = CreateHash(Name, 1, 0, 0x3E8);
K[4] = (VALUE & 0XFF);
K[5] = ((VALUE >> 0X8) & 0XFF);
K[6] = ((VALUE >> 0X10) & 0XFF);
K[7] = ((VALUE >> 0X18) & 0XFF);

//根据逆向的算法算出其余的字节
while (1)
{
byte k0 = rand() % 0xFF;
DWORD ECX = 0XFF & (((k0 ^ K[6] ^ 0X18) + 0X3D) ^ 0XA7);
if (ECX >= 0xA)
{
K[0] = k0;
break;
}
}

while (1)
{
byte k1 = rand() % 0xFF;
byte k2 = rand() % 0xFF;

DWORD NUM = (0XFFFF & (0X3421 ^ (((0xFFFF & (0X100 * (k1 ^ K[7] & 0XFF) + (K[5] ^ k2 & 0XFF))) ^ 0X7892) + 0X4D30)));
DWORD EDX = NUM % 0XB;
DWORD EAX = NUM / 0XB;
if (EAX != 0 && EAX == 0X3E8)
{
if (EDX == 0)
{
K[1] = k1;
K[2] = k2;
break;
}
}
}
printf("序列号为:\n");
//打印出序列号
printf( "%02X%02X-%02X%02X-%02X%02X-%02X%02X"、
K [0]、K [1]、K [2]、K [3]、K [4]、K [5]、K [6]、K [7])。
getchar関数();
0を返します。   
}

シーケンス番号を取得するためにユーザー名を入力して実行した後

1565953670106

そして、あなたが正常に登録を確認することができ、登録するには、このユーザ名とシリアル番号を使用して、RIの書き込みは完了です。

1565953677634

----------------

おすすめ

転載: www.cnblogs.com/ltyandy/p/11365894.html