首页
社区
课程
招聘
[旧帖] [原创]某易语言程序完美破解[申请邀请码] 0.00雪花
发表于: 2014-11-13 19:45 9983

[旧帖] [原创]某易语言程序完美破解[申请邀请码] 0.00雪花

2014-11-13 19:45
9983
程序下载地址:
http://pan.baidu.com/s/1ntHRiyt
首先PEID查壳是没有壳,看区段大家不难发现其实是有壳的,OD能正常调试,所以我们就不脱壳了。

在这里点注册,注册码是绑定账号,不绑定电脑的,所以根据账号应该有个算法计算注册码的。

从点注册的地方开始分析,跟了一段就到了一大堆跳转里面去了,分析不出个头绪。
换个思路,运行后dump出来查一下看有没有什么算法,如图


账号长度是不确定的,作者给的key是256位的,DES的话不会改变长度,那么算法很明显是RSA了。256位16进制数就是二进制1024位,应该是标准的RSA1024。
易语言的RSA有什么特征呢,易的作者一般不会自己去写这种算法,估计有模块。
上易的论坛看了看,数据操作支持库里面有加密相关的操作,
安装了个易语言,然后发现有个RSACheck

自己写了个简单的程序调用这个函数,然后OD里面调,可以定位出这个函数的特征码:
B8 34 20 00 00 E8 ?? ?? ?? ?? 53 55 56 8B B4 24 ?? ?? ?? ?? 8D 44 24 10 57 8B 4E 0C 33 DB 50 51 89 5C 24 24 89 5C 24 20 89 5C 24 18 89 5C 24 1C
OD里面CTRL+B搜索,果然有,那就是这个函数无疑了!

观察这个函数的参数可以发现那么只要找到公钥和模数就可以了。
先调试了一会自己那个简单的程序,知道了那2个参数在什么位置传入的,
然后调试了一下那个程序,发一个很可疑的字符串,1032B估计就是公钥了,后面那个256位的字符串是模数。

然后自己把参数带入自己的程序测试,生成的注册码一模一样了,成功了!
然后写注册机

我又测试了另外几个号,结果输入了注册码还是注册不成功,看来还有暗桩。
我是自己算的号,没有爆破,他怎么设置暗桩呢?估计还有网络验证了。
下断点bp ws2_32.send
发现访问了一个网易博客

里面的内容是一串乱七八糟的字符,
{orochigg1dz}

8QuRsPpQwAiDlA6TkAiRlToPiRjTsPlRvTkAZR2RlT3PvR7E2PlR8TlA2R7T1PvR8TlApRYEpAPRmEmAoCYEpACRtT2AnCCTvAoC8ErPjR2TmPBR1TmA5P2RsE5PrCrEoA6RpEpAwC5T3PsC6TmAmCrE1PnCt

EnAuBoD6UnB4SpF3Q0S7FZQrDZU6QZSZUmB0SwD0UmBrD2U4Q4S3UvBsDqF6QwDpFrBnD6UrBxD2UvBZSmFrBwDnF3Q5SoF2QnDZUlB8StU5Q{orochi2001}
{orochizzdh}fgJeIeuJeeqKOddfOOqdxK4axIGfJOnIdfmaSdrfvaFdvK8KROvIIfAOzIyfJOCZHfIOJdTfdOXddfPOxIGfra2IGfxaiC7EkAiC7E{orochi2001}
{orochiggy}ra7LScuJNc2awJncjSpUtQrSBUkBiDuU8QkStUsBnDmFnBnDqFpBwD8FtQ1SiU2Q1SkS8F1QkS7UkBoSZUZQpS5U8QjDlUtQmS{orochi2001}
{orochihmd}zEmFoFsEuBmFpBlD{orochi2001}
{orochigxrz}

tJjcvKBg7LzJ8R7U7SqFrBjDqFnBjDsFnBjDqF6FecxezLOcPeNgSc5JJgaclDAgVcKergsbaeKgAYMeegsbaeBgIclDAgjbSejLEcxJJgbORdtKiADdiIPfwOtI8KROvIPfwOuIlKcOIdbfxavCvKEOwIafy

aGZdfPODdJfRO1drKCOddTfROrIdfjaNdUfBO8aed7Ksa6dwKBOTdhfiASdrfCOsIKfraAdA1MOGd{orochi2001}
{orochixzdz}kTpUuRtUvD8EjCsT0PkR7E1P2RlT3PvR7E2PlR8TlApR8EnAkRoTRPIRlTxPuR{orochi2001}
{orochixzdz2}{orochi2001}
{orochixzdzrz}

ybYdvICcIePOgehOrKhOddtK4ayIiRoTsPqRATlAjCZTkPiCqTlP2R7TkPiC6TnPnR8E2PoCiTqAjRnE7P2RsEpA2IiK7PuRoToPuC8ElAoP2RiTkAZR4T8P5RpTkA0RjTlPjCvTlApCiTsPTROT8PzRoT

{orochi2001}
{orochizcmd}

xDmEtEmDmEnCqEsAmC5ErApCsEtAsCyEsArCoEiApCpEmArCzEoApCpEtAkCtEuArCyEpAwCmEpApC5EvAmCzEsAmAoCzEiAxCsEvAsCqEmAmC5EqAoCmEuAwCpErAwCoEiApCsEsAnCzEsAxCpEnAsC5ErAm

CoEqAnCyEmEnAsC5EpAnBnDoFqBqDrFuBsD6F{orochi2001}
{orochiybmd}

kCtCsCoCtEsFpAtBoFjBoDoFvBtDrFoBqDsFqBqBlDpFnBrDzFrBmD6FmBrDtFnAqCqEmAqCqEiAnCsEuAmCtEsAtCoEnAkCsEqAxCqEqAwCtEoAtC5EvAuAwCnEpAwCyEuAwC5EtAqCpEvAnCoEmAxCsEiAn

CnEnAqCyEnAqCqEnAkCyErAsCyEuArCoEmApC5EmEpAtCoEoAsCqEpAmC5EoAmCyEvAoCnEvAmCqE6FrBmDyFuBnDzFuBoD6FrBsDmFrBoDnFmBoDsFjBpBtDzFtBoDzFoBsDnFrBlDpFoBsDyFsBxDoFpBnD

6F{orochi2001}
{orochibb}72{orochi2001}
估计这个就是白名单了,前面看到的DES和BASE64什么的算法可能就在这里。
在OD里面调了一下这个解密过程,从一个JMP之后又是一段很乱的反汇编代码
00D7B21D    51              push ecx
00D7B21E    881C24          mov byte ptr ss:[esp],bl
00D7B221    60              pushad
00D7B222    C74424 20 2B7DC>mov dword ptr ss:[esp+0x20],0xADC77D2B
00D7B22A    68 ED4B8312     push 0x12834BED
00D7B22F    E8 028EF2FF     call Q宠迷你?00CA4036
00D7B234    DFEF            fucomip st,st(7)
00D7B236    CB              retf
00D7B237    6377 9D         arpl word ptr ds:[edi-0x63],si
00D7B23A    79 23           jns XQ宠迷你?00D7B25F
00D7B23C    8BA1 6438FCDE   mov esp,dword ptr ds:[ecx+0xDEFC3864]
00D7B242    BE 90662E06     mov esi,0x62E6690
00D7B247    F0:C8 9E348E    lock enter 0x349E,0x8E                   ; 不允许锁定前缀
00D7B24C    F9              stc
00D7B24D    5C              pop esp
00D7B24E    1AB7 1EDEF453   sbb dh,byte ptr ds:[edi+0x53F4DE1E]
00D7B254    0E              push cs
00D7B255    A4              movs byte ptr es:[edi],byte ptr ds:[esi]
00D7B256    97              xchg eax,edi
00D7B257    6C              ins byte ptr es:[edi],dx
00D7B258    B2 11           mov dl,0x11
00D7B25A    C8 BF9C56       enter 0x9CBF,0x56

先想想其他办法,既然是白名单,内存里面看有没有,回到401000搜索一下字符串。
发现了2个列表。估计是白名单了。

但是感觉怎么才这么点账号。可能还有个列表不在text区段。
再找了一下,又发现了一个列表:

剩下的问题很简单了,内存修改。
参考了《加密解密第三版》18.2.4 DLL劫持技术的例子稍微改改就能用了。

#include <Windows.h>

#define EXTERNC extern "C"
#define NAKED __declspec(naked)
#define EXPORT __declspec(dllexport)

#define ALCPP EXPORT NAKED
#define ALSTD EXTERNC EXPORT NAKED void __stdcall
#define ALCFAST EXTERNC EXPORT NAKED void __fastcall
#define ALCDECL EXTERNC EXPORT NAKED void __cdecl
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <list>
using namespace std;
list<MEMORY_BASIC_INFORMATION>	MemList ;
SYSTEM_INFO		SysInfo ;
MEMORYSTATUS	MemStatus ;
#include <TlHelp32.h>
#define STRINGLEN 8
BOOL bRunning = FALSE;
BOOL bFind=FALSE;

DWORD WINAPI SearchAndModify(LPVOID lParam)
{
#ifdef _DEBUG
	CHAR tip[100]={0};
#endif
	DWORD dwSAddr=0x401000;
	BYTE pHeader[2]={0x33,0xC0};
	if(bRunning)
		return 1;
	bRunning=TRUE;
	Sleep(5000);
	while(1)
	{
		if(memcmp((LPVOID)dwSAddr, pHeader, 2)==0)//先让壳把程序解压后再搜索内存
			break;
		Sleep(1000);
	}
	GetSystemInfo ( &SysInfo ) ;
	HANDLE hProcess = INVALID_HANDLE_VALUE;
	
	//第一步 查询
	MEMORY_BASIC_INFORMATION	MemBaseInfo ;
	BYTE pPatternBuffer[STRINGLEN]={0x34,0x34,0x31,0x32,0x35,0x32,0x39,0x37};//原始账号
	BYTE pWrite[STRINGLEN]=		   {0x31,0x34,0x36,0x32,0x32,0x30,0x38,0x34};//修改后的账号(随便写的,不是我的号)
	while(1)
	{
		
		DWORD dwInfoSize = sizeof(MEMORY_BASIC_INFORMATION) ;
		DWORD dwCurPos =(DWORD)SysInfo.lpMinimumApplicationAddress ;
		DWORD dwMax=0x06000000;//(DWORD)SysInfo.lpMaximumApplicationAddress ;
		while ( dwCurPos < dwMax)
		{
			VirtualQuery((LPVOID)dwCurPos, &MemBaseInfo, dwInfoSize ) ;// 查询进程的指定地址的状态信息
		if(MEM_COMMIT==MemBaseInfo.State && PAGE_READWRITE==MemBaseInfo.Protect)//检测是否为“提交”状态 检测是否可读
		{
#ifdef _DEBUG
			wsprintf(tip,"base:%X ,size:%X ReadWrite",MemBaseInfo.BaseAddress,MemBaseInfo.RegionSize);
			OutputDebugString(tip);
#endif
			if(MemBaseInfo.RegionSize==0x100000)//检测内存大小
				goto start;//跳出2层while
		}

			// 定位到下一个区域
			dwCurPos = (DWORD)MemBaseInfo.BaseAddress + MemBaseInfo.RegionSize ;
		}
		Sleep(1000);
	}
start:
	MEMORY_BASIC_INFORMATION *p=&MemBaseInfo;
	LPBYTE  lpAddr = (LPBYTE )((DWORD)p->BaseAddress) ;
#ifdef _DEBUG
	wsprintf(tip,"Find memory: base:%X ,size:%X",lpAddr,p->RegionSize);
	OutputDebugString(tip);
#endif
		

	DWORD dwSize = 0, dwReadBytes = 0  ;
	while(1)
	{
		for ( int i = 0; i < p->RegionSize; i++ )
		{
	#ifdef _DEBUG
			wsprintf(tip,"lpAddr[i]:%X",&lpAddr[i]);
			OutputDebugString(tip);
	#endif
			if(memcmp(&lpAddr[i], pPatternBuffer, STRINGLEN)==0)
			{
				if(&lpAddr[i]==pPatternBuffer)//字符本身不改
					continue;
				bFind=TRUE;
				DWORD dwWriteBytes = 0  ;
	#ifdef _DEBUG
				OutputDebugString("Find success!!");
	#endif
				
				//VirtualProtect ( (LPVOID)&lpAddr[i], STRINGLEN, PAGE_READWRITE, &dwOldProtect ) ; 
				memcpy(&lpAddr[i],pWrite,STRINGLEN);
				//VirtualProtect (  (LPVOID)&lpAddr[i], STRINGLEN, dwOldProtect, NULL ) ;
				continue;
			}
		}
		if(bFind)
			break;
		else
			Sleep(1000);
	}
	OutputDebugString("over");
	return 0;
}

namespace MemCode
{
	HMODULE m_hModule = NULL;		// 原始模块句柄
	DWORD m_dwReturn[500] = {0};	// 原始函数返回地址
	
	// 加载原始模块
	inline BOOL WINAPI Load()
	{
		TCHAR tzPath[MAX_PATH]={0};
		TCHAR tzTemp[MAX_PATH]={0};
		
		GetSystemDirectory(tzPath, sizeof(tzPath));
		strcat(tzPath,"\\lpk.dll");
		m_hModule = LoadLibrary(tzPath);
		if (m_hModule == NULL)
		{
			wsprintf(tzTemp, TEXT("无法加载 %s,程序无法正常运行。"), tzPath);
			MessageBox(NULL, tzTemp, TEXT("MemCode"), MB_ICONSTOP);
		}

		return (m_hModule != NULL);	
	}
	
	// 释放原始模块
	inline VOID WINAPI Free()
	{
		if (m_hModule)
		{
			FreeLibrary(m_hModule);
		}
	}
	
	// 获取原始函数地址
	FARPROC WINAPI GetAddress(PCSTR pszProcName)
	{
		FARPROC fpAddress;
		TCHAR szProcName[16]={0};
		TCHAR tzTemp[MAX_PATH]={0};
		
		if (m_hModule == NULL)
		{
			if (Load() == FALSE)
			{
				ExitProcess(-1);
			}
		}
		
		fpAddress = GetProcAddress(m_hModule, pszProcName);
		if (fpAddress == NULL)
		{
			if (HIWORD(pszProcName) == 0)
			{
				wsprintf(szProcName, "%d", pszProcName);
				pszProcName = szProcName;
			}
			
			wsprintf(tzTemp, TEXT("无法找到函数 %hs,程序无法正常运行。"), pszProcName);
			MessageBox(NULL, tzTemp, TEXT("MemCode"), MB_ICONSTOP);
			ExitProcess(-2);
		}
		
		return fpAddress;
	}
}

win7不加载这个dll,改了一下注册表重启就好了。测试了一下,注册成功。
然后这份代码有个bug,运行后可能会崩溃,内存错误,也可能不崩溃,我后来改好了。我故意留给大家当做思考题吧。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 193
活跃值: (847)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
真是高人啊  看着眼迷离
2014-11-13 21:17
0
雪    币: 2
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼主我膜拜你,你太牛啦
2014-11-14 21:13
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主给我很大的启发,谢谢!
2014-11-18 16:57
0
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
太厉害了
2014-11-18 17:58
0
雪    币: 8150
活跃值: (3301)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
除了膜拜没什么其他说法了,收藏备用
2014-11-21 11:05
0
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
支持,看那段代码,经常玩C的
2014-11-21 11:34
0
游客
登录 | 注册 方可回帖
返回
//