菜鸟 学注册机编写之 “RSA”
测试环境
系统: xp sp3
调试器 :od 1.10
RSA简单介绍
选取两个别人不知道的大素数p, q.
公共模n = p*q
欧拉值φ(n) = (p-1)(q-1)
选取公匙(加密匙) e , 条件是1< e <φ(n),且e与φ(n) 互质. 常用为3, 65537等.
根据扩展欧几里德算法求得:
私匙 d = e^-1 mod φ(n) .
加解密算法:
加密: 密文c = m^e mod n
解密: 明文 m = c^d mod n
一: 定位关键CALL
1.OD载入程序, F9运行, 点击”Register”随便输入用户名与注册码,如下图

2.点击 “暂停” 点击 “K” ,来到如下图的地方

3.点”显示调用” 往上找就能找到关键跳与关键CALL,如下 地方
81EC sub esp,0x200
push esi
6A push 0x1
8BF1 mov esi,ecx
0040283B E8 D0020900 call Apollo_3.00492B10 ; jmp 到 mfc42.#?UpdateData@CWnd@@QAEHH@Z_6334
8B86 mov eax,dword ptr ds:[esi+0x134] ; 注册码
8B8E mov ecx,dword ptr ds:[esi+0x138] ; 用户名
0040284C push eax
0040284D push ecx
0040284E E8 2DE50000 call Apollo_3.00410D80 ; 关键Call
83C4 add esp,0x8
85C0 test eax,eax
1B jnz short Apollo_3. ; 关键跳
0040285A 6A push 0x40
0040285C B0724C00 push Apollo_3.004C72B0 ; ASCII "抱歉"
88724C00 push Apollo_3.004C7288 ; ASCII "无效的用户名或注册码"
8BCE mov ecx,esi
E8 9D020900 call Apollo_3.00492B0A ; jmp 到 mfc42.#?MessageBoxA@CWnd@@QAEHPBD0I@Z_4224
0040286D 5E pop esi
0040286E 81C4 add esp,0x200
C3 retn
4.分析关键Call
00410D80 6A FF push -0x1
00410D82 095A4900 push Apollo_3.00495A09
00410D87 :A1 mov eax,dword ptr fs:[]
00410D8D push eax
00410D8E : >mov dword ptr fs:[],esp
00410D95 81EC sub esp,0x94
00410D9B 8B8424 A4000000 mov eax,dword ptr ss:[esp+0xA4]
00410DA2 push ebx
00410DA3 push esi
00410DA4 push eax
00410DA5 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
00410DA9 C74424 5F144>mov dword ptr ss:[esp+0x60],0xE14B145F ; 初始化 模n
00410DB1 C74424 86C6C>mov dword ptr ss:[esp+0x64],0xEC9C686
00410DB9 C74424 1969E>mov dword ptr ss:[esp+0x68],0x6BEF6919
00410DC1 C74424 6C 63CF1>mov dword ptr ss:[esp+0x6C],0xCC14CF63
00410DC9 C74424 CDB41>mov dword ptr ss:[esp+0x70],0x2D15B4CD
00410DD1 C74424 B1716>mov dword ptr ss:[esp+0x74],0xA26E71B1
00410DD9 C74424 CD44C>mov dword ptr ss:[esp+0x78],0xDDCC44CD
00410DE1 C74424 7C >mov dword ptr ss:[esp+0x7C],0x5C4D0602
00410DE9 E8 B61C0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
00410DEE 8B8C24 B0000000 mov ecx,dword ptr ss:[esp+0xB0]
00410DF5 C78424 A4000000>mov dword ptr ss:[esp+0xA4],0x0
00410E00 push ecx
00410E01 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
00410E05 E8 9A1C0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
00410E0A 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
00410E0F 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
00410E13 C68424 A8000000>mov byte ptr ss:[esp+0xA8],0x1
00410E1B E8 D81F0800 call Apollo_3.00492DF8 ; jmp 到 mfc42.#?TrimLeft@CString@@QAEXPBD@Z_6928
00410E20 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
00410E25 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
00410E29 E8 C41F0800 call Apollo_3.00492DF2 ; jmp 到 mfc42.#?TrimRight@CString@@QAEXPBD@Z_6930
00410E2E 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
00410E33 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
00410E37 E8 BC1F0800 call Apollo_3.00492DF8 ; jmp 到 mfc42.#?TrimLeft@CString@@QAEXPBD@Z_6928
00410E3C 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
00410E41 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
00410E45 E8 A81F0800 call Apollo_3.00492DF2 ; jmp 到 mfc42.#?TrimRight@CString@@QAEXPBD@Z_6930
00410E4A 8B5424 0C mov edx,dword ptr ss:[esp+0xC]
00410E4E 8B35 68AD4900 mov esi,dword ptr ds:[0x49AD68] ; msvcrt._mbscmp
00410E54 285E4D00 push Apollo_3.004D5E28
00410E59 push edx
00410E5A FFD6 call esi ; 判断用户名是否为空 mbscmp
00410E5C 83C4 add esp,0x8
00410E5F 85C0 test eax,eax
00410E61 0F84 0F020000 je Apollo_3.
00410E67 8B4424 mov eax,dword ptr ss:[esp+0x8]
00410E6B 285E4D00 push Apollo_3.004D5E28
00410E70 push eax
00410E71 FFD6 call esi ; 判断注册码是否为空
00410E73 83C4 add esp,0x8
00410E76 85C0 test eax,eax
00410E78 0F84 F8010000 je Apollo_3.
00410E7E push edi
00410E7F 6A push 0x0
00410E81 8D4C24 lea ecx,dword ptr ss:[esp+0x44]
00410E85 E8 261F0000 call Apollo_3.00412DB0
00410E8A 6A push 0x0
00410E8C 8D4C24 4C lea ecx,dword ptr ss:[esp+0x4C]
00410E90 C68424 AC000000>mov byte ptr ss:[esp+0xAC],0x2
00410E98 E8 131F0000 call Apollo_3.00412DB0
00410E9D B3 mov bl,0x3
00410E9F push 0x10001 ; 公钥 e 10001
00410EA4 8D4C24 5C lea ecx,dword ptr ss:[esp+0x5C]
00410EA8 889C24 AC000000 mov byte ptr ss:[esp+0xAC],bl
00410EAF E8 FC1E0000 call Apollo_3.00412DB0 ; cinstr(e,"10001")初始化公钥e
00410EB4 8D4C24 lea ecx,dword ptr ss:[esp+0x58]
00410EB8 C68424 A8000000>mov byte ptr ss:[esp+0xA8],0x4
00410EC0 push ecx
00410EC1 8D4C24 4C lea ecx,dword ptr ss:[esp+0x4C]
00410EC5 E8 461F0000 call Apollo_3.00412E10
00410ECA 8D4C24 lea ecx,dword ptr ss:[esp+0x58]
00410ECE 889C24 A8000000 mov byte ptr ss:[esp+0xA8],bl
00410ED5 E8 861F0000 call Apollo_3.00412E60
00410EDA 8D5424 lea edx,dword ptr ss:[esp+0x60]
00410EDE 6A push 0x8
00410EE0 push edx
00410EE1 8D4C24 lea ecx,dword ptr ss:[esp+0x48]
00410EE5 E8 961D0000 call Apollo_3.00412C80 ; 将模N转换成大数
00410EEA B9 mov ecx,0x8
00410EEF 33C0 xor eax,eax
00410EF1 8D7C24 lea edi,dword ptr ss:[esp+0x18]
00410EF5 8D5424 2C lea edx,dword ptr ss:[esp+0x2C]
00410EF9 F3:AB rep stos dword ptr es:[edi]
00410EFB 8D4424 lea eax,dword ptr ss:[esp+0x34]
00410EFF 8D4C24 lea ecx,dword ptr ss:[esp+0x30]
00410F03 push eax
00410F04 push ecx
00410F05 8D4424 lea eax,dword ptr ss:[esp+0x30]
00410F09 push edx
00410F0A 8D4C24 lea ecx,dword ptr ss:[esp+0x30]
00410F0E push eax
00410F0F 8D5424 lea edx,dword ptr ss:[esp+0x30]
00410F13 push ecx
00410F14 8D4424 lea eax,dword ptr ss:[esp+0x30]
00410F18 push edx
00410F19 8B5424 mov edx,dword ptr ss:[esp+0x24]
00410F1D 8D4C24 lea ecx,dword ptr ss:[esp+0x30]
00410F21 push eax
00410F22 push ecx ; 注册码格式成16进制数据
00410F23 0C914C00 push Apollo_3.004C910C ; ASCII "%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX\n"
00410F28 push edx
00410F29 FF15 98AD4900 call dword ptr ds:[0x49AD98] ; msvcrt.sscanf
00410F2F 8B4424 mov eax,dword ptr ss:[esp+0x50] ; sn5
00410F33 8B4C24 4C mov ecx,dword ptr ss:[esp+0x4C] ; sn4
00410F37 8B7C24 mov edi,dword ptr ss:[esp+0x48] ; sn3
00410F3B 8B5424 mov edx,dword ptr ss:[esp+0x44] ; sn2
00410F3F 03C1 add eax,ecx ; sn5 = sn5+sn4
00410F41 8B4C24 5C mov ecx,dword ptr ss:[esp+0x5C] ; sn8
00410F45 03C7 add eax,edi ; sn5 = (sn5+sn4)+sn3
00410F47 8B7C24 mov edi,dword ptr ss:[esp+0x58] ; sn7
00410F4B 03C2 add eax,edx ; sn5 = (sn5+sn4+sn3)+sn2
00410F4D 8B5424 mov edx,dword ptr ss:[esp+0x40] ; sn1
00410F51 33C8 xor ecx,eax ; sn8 ^= (sn5+sn4+sn3+sn2)
00410F53 8B4424 mov eax,dword ptr ss:[esp+0x54] ; sn6
00410F57 83C4 add esp,0x28
00410F5A 03C2 add eax,edx ; sn6 = sn6+sn1
00410F5C 894C24 mov dword ptr ss:[esp+0x34],ecx ; 存放sn8 ^= (sn5+sn4+sn3+sn2)
00410F60 33F8 xor edi,eax ; sn7 ^= (sn6+sn1)
00410F62 6A push 0x0
00410F64 8D4C24 3C lea ecx,dword ptr ss:[esp+0x3C]
00410F68 897C24 mov dword ptr ss:[esp+0x34],edi ; 存放sn7 ^= (sn6+sn1)
00410F6C E8 3F1E0000 call Apollo_3.00412DB0
00410F71 8D4C24 lea ecx,dword ptr ss:[esp+0x18]
00410F75 6A push 0x8
00410F77 push ecx
00410F78 8D4C24 lea ecx,dword ptr ss:[esp+0x40]
00410F7C C68424 B0000000>mov byte ptr ss:[esp+0xB0],0x5
00410F84 E8 F71C0000 call Apollo_3.00412C80
00410F89 8D5424 lea edx,dword ptr ss:[esp+0x38]
00410F8D 8D4424 lea eax,dword ptr ss:[esp+0x50]
00410F91 push edx
00410F92 push eax
00410F93 8D4C24 lea ecx,dword ptr ss:[esp+0x48] ; 指向注册计算出来的数
00410F97 E8 call Apollo_3. ; powmod c= m^e mod n
00410F9C B9 mov ecx,0x8
00410FA1 33C0 xor eax,eax
00410FA3 8D7C24 lea edi,dword ptr ss:[esp+0x18]
00410FA7 6A push 0x8
00410FA9 F3:AB rep stos dword ptr es:[edi] ; 清空
00410FAB 8D4C24 1C lea ecx,dword ptr ss:[esp+0x1C]
00410FAF C68424 AC000000>mov byte ptr ss:[esp+0xAC],0x6
00410FB7 push ecx
00410FB8 8D4C24 lea ecx,dword ptr ss:[esp+0x58]
00410FBC E8 FF1C0000 call Apollo_3.00412CC0 ; big_to_bytes
00410FC1 B9 mov ecx,0x8
00410FC6 33C0 xor eax,eax
00410FC8 8DBC24 lea edi,dword ptr ss:[esp+0x80]
00410FCF F3:AB rep stos dword ptr es:[edi]
00410FD1 5F pop edi
00410FD2 8A5404 mov dl,byte ptr ss:[esp+eax+0x17] ; 循环交换数据位置 4字节一组 应当是小端转大端操作
00410FD6 8A4C04 mov cl,byte ptr ss:[esp+eax+0x16]
00410FDA 7C mov byte ptr ss:[esp+eax+0x7C],dl
00410FDE 8B5404 mov edx,dword ptr ss:[esp+eax+0x14]
00410FE2 884C04 7D mov byte ptr ss:[esp+eax+0x7D],cl
00410FE6 8A4C04 mov cl,byte ptr ss:[esp+eax+0x14]
00410FEA C1EA shr edx,0x8
00410FED 7E mov byte ptr ss:[esp+eax+0x7E],dl
00410FF1 884C04 7F mov byte ptr ss:[esp+eax+0x7F],cl
00410FF5 83C0 add eax,0x4
00410FF8 83F8 cmp eax,0x20
00410FFB ^ 7C D5 jl short Apollo_3.00410FD2 ; 判断是否结束
00410FFD 8D5424 7C lea edx,dword ptr ss:[esp+0x7C]
8D4C24 lea ecx,dword ptr ss:[esp+0x10]
push edx
E8 991A0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
0041100B 8B4424 mov eax,dword ptr ss:[esp+0x10]
0041100F 8B4C24 0C mov ecx,dword ptr ss:[esp+0xC]
push eax
push ecx
FFD6 call esi ; 比较用户名是否相同
83C4 add esp,0x8
0041101A 8D4C24 lea ecx,dword ptr ss:[esp+0x10]
0041101E 85C0 test eax,eax
C68424 A4000000>mov byte ptr ss:[esp+0xA4],0x6
0F84 je Apollo_3.004110B4
算法分析总结
以上是注册的第一步,检查是否受到用户名和注册码的输入,如果没有输入就返回 false,同时,也已经找到了 RSA 算法中的公钥 e 和模 n,可以进入下一步参与大数运算了.
我们现在可以分解N 然后得到D
如下图

注册码格式是 s0-s1-s2-s3-s4-s5-s6-s7,首先把 s6 和 s7 原先处理一下,处理的方法是:
s6 = ( s0 + s5 ) ^ s6
s7 = ( s1 + s2 + s3 + s4 ) ^ s7
二:注册码机编写
1. 注册机源码
#include <stdio.h>
#include <windows.h>
#include "MIRACL.H" #pragma comment(lib,"ms32.lib") #if _DEBUG
#pragma comment(linker,"/NODEFAULTLIB:LIBC")
#endif void hex_to_str(char *ptr,unsigned char *buf,int len)
{
int i=;
for(i = ; i < len; i++)
{
sprintf(ptr, "%02x",buf[i]);
ptr += ;
}
} void main()
{ miracl* mip=mirsys(,);
char szName[]={};
unsigned char hexstring[] = {};
unsigned char UserSun[] = {};
char License[] = {};
char szSerial[] = {};
int i, j;
big n,d,c,m;
long dtLength;
unsigned char temp[] = {};
unsigned int SN[] = {}; printf("------HA-Apollo3GP_362 注册码机-------\n\n"); printf("请输入用户名:");
scanf("%s",szName); if (strlen(szName) > )
{
printf("用户名不长度不能大于240\n");
return;
} //将用户名转换成10进制值并逆转 for (i =; i<strlen(szName); i++)
{
UserSun[i] = toascii(szName[i]);
} //交换位置
j =;
for (; i>; i-=)
{ strncpy(temp, UserSun+j, );
strncpy(UserSun+j, UserSun+i-, );
strncpy(UserSun+i-,temp, );
j+=;
} hex_to_str(hexstring, UserSun, strlen(UserSun)); dtLength = strlen(hexstring);
mip->IOBASE=; // 16进制模式
c=mirvar(); // MIRACL的大数类型
n=mirvar();
d=mirvar();
m=mirvar(); cinstr(c,hexstring); // 将用户名转换成大数
cinstr(n,"5C4D0602DDCC44CDA26E71B12D15B4CDCC14CF636BEF69190EC9C686E14B145F"); // 初始化模数n
cinstr(d,"D32AA4860A4A3B5EFA2F138CF648A2CB1C889773DFD90D95AC93B6D76E08FB9"); // 初始化私钥d
powmod(c,d,n,m); // 计算m = (c ^ d) mod n
cotstr(m,szSerial); //组合注册码
//SN7 = SN7 ^ (sn6+sn1)
//SN8 = SN8 ^ (sn5+sn4+sn3+sn2) //-每4字节进行计算
memset(UserSun, , strlen(UserSun));
j = ; //逆序组合注册码格式
for (i = strlen(szSerial); i>; i -= )
{
strncpy(UserSun+j, szSerial+i-, ); if (i !=)
{
strcat(UserSun,"-");
} j += ;
} //--格式化成16进制数据 dword值 j = ;
for (i=; i<strlen(UserSun)-; i+=)
{
sscanf(UserSun+i+j, "%08lX", SN+j);
j += ;
} //SN7 = SN7 ^ SN1+ SN6;
//SN8 = SN8 ^ (sn5+sn4+sn3+sn2)
SN[-] = SN[-] ^ (SN[-]+SN[-]);
SN[-] = SN[-] ^ (SN[-]+SN[-]+SN[-]+SN[-]); //-将16进制转换成字符串 //-生成最终注册码
j=;
for (i=; i<; i++)
{
sprintf(License+j, "%08X", SN[i]);
if (i != )
{
strcat(License, "-");
} j+=;
} printf("注册码: %s\n",License);
system("pause"); }
2. 测试注册机
输入用户名test

成功注册

完。
样本及注册机源码下载
http://yunpan.cn/cAqLfTSHxYBvX (提取码:3855)
菜鸟 学注册机编写之 “RSA”的更多相关文章
- 菜鸟 学注册机编写之 “MD5”
测试环境 系统: xp sp3 调试器 :od 1.10 sc_office_2003_pro 高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激! 一:定位关键CALL 1. 因 ...
- 菜鸟 学注册机编写之 Android app
0x00前言 环境及工具: 手机 Nexus 4(己root) 系统版本 Android 5.01 工具 AndroidKiller_V1.2 关于Android平台app注册机的编 ...
- 菜鸟 学注册机编写之 “sha1”
1. 首先运行程序随便输入用户与注册码如下图所示: 2.将程序载入OD, 下MessageBoxA函数断点, F9运行程序, 程序运行后随便输入用户名与注册码,点"OK"后断下,F ...
- 010 Editor 8.0.1 之 逆向分析及注册机编写
前言一.工具及软件介绍二.逆向分析2.1.找到提示错误注册弹窗2.2.分析跳转处代码2.3.=2D 函数分析2.3.1.获取注册码处分析2.3.2.3处分支分析2.3.2.1.9C情况2.3.2.2. ...
- 010 Editor v8.0.1(32 - bit) 算法逆向分析、注册机编写
010 Editor 的逆向分析整体算下来还是比较简单的,将程序拖入OD,通过字符串搜索定位到核心代码,经过分析,主要是如下图所示的两个关键函数,返回正确的值,才算是注册成功. 00409C9B 这个 ...
- OD 实验(十八) - 简单注册机的编写
程序: 运行 这是一个注册机 随便输入点内容,点击 Check 弹出错误的对话框 逆向: 用 OD 载入程序 在文本框处下断点 按 Alt+B 查看断点 这个断点在动态链接库那里 跑一下程序,输入内容 ...
- 用C#.NET编写软件注册机
验证注册码是保护软件产品产权的常用手段.一般过程如下, 1. 软件发行者收集用户特有的信息: 2. 根据用户特有的信息,使用注册机生成注册码并把注册码发给客户: 3. 向软件导入注册码,由软件自 ...
- 【转】破解Source Insight 3.5.0072过程 附:安装软件+注册机
转载地址:http://blog.csdn.net/qs_hud/article/details/8884867 注册机及软件下载地址:http://download.csdn.net/detail/ ...
- 菜鸟学自动化测试(八)----selenium 2.0环境搭建(基于maven)
菜鸟学自动化测试(八)----selenium 2.0环境搭建(基于maven) 2012-02-04 13:11 by 虫师, 11419 阅读, 5 评论, 收藏, 编辑 之前我就讲过一种方试来搭 ...
随机推荐
- 14、/proc/cpuinfo 文件(查看CPU信息)
转载http://www.cnblogs.com/itcomputer/p/4888438.html /proc/cpuinfo文件分析 根据以下内容,我们则可以很方便的知道当前系统关于CPU.CPU ...
- iOS开发,使用CocoaSSDP查找设备时按关键字过滤Device
关于CocoaSSDP的资料有很多,这里就不介绍了. 希望寻找的目标设备,在header中设置了自定义的keyword,虽然通过外围代码也能达到相同目的,但是直接修改CocoaSSDP源码更简便. 导 ...
- Entity Framework Code-First(13):Configure Many-to-Many
Configure Many-to-Many relationship: Here, we will learn how to configure Many-to-Many relationship ...
- 9. CTF综合靶机渗透(二)
靶机说明 Welcome to the world of Acid. Fairy tails uses secret keys to open the magical doors. 欢迎来到酸的世界. ...
- Windows10安装node.js,vue.js以及创建第一个vue.js项目
[工具官网] Node.js : http://nodejs.cn/ 淘宝NPM: https://npm.taobao.org/ 一.安装环境 1.本机系统:Windows 10 Pro(64位)2 ...
- Boost Python学习笔记(二)
你将学到什么 如何在Python中调用C++代码 如何在C++中调用Python代码 在Python中调用C++代码 首先定义一个动物类(include/animal.h) #pragma once ...
- Linux之shell备份数据库
功能概述: 使用shell脚本对服务器的数据库(全部或指定数据库)进行备份.对15天(固定天数)之前的数据库备份进行删除 命令实现: 待定
- ThinkSNS+ PHP开发概述
Plus (读音:[plʌs],全称:ThinkSNS+ [θɪŋk es en es plʌs],是 ThinkSNS 系列产品一个重要版本,其软件识别名称为 Plus 即 +) 是一个基于 Lat ...
- htmlunit最具有参考意义项目
### HtmlUnit What? - 项目1 https://gitee.com/dgwcode/spiderTmallTradeInfo - 项目2 https://gitee.com/dgwc ...
- 解决Eclipse导入Gradle项目时在 Building gradle project info 一直卡住
问题描述 在使用 Eclipse 导入 Gradle 项目时一直卡住,不能导入项目 问题解决 解决办法主要有两种:一是直接下载 gradle 离线包,二是修改项目的 ..\gradle\wrapp ...