网页 序列号 逆向linux,逆向序列号生成算法(一)

对逆向工程一直很感兴趣,工作之余自己也研究一下,好久没有练手了,OllyDBG的使用都感觉生疏了,晚上抽空先去补了补OllyDBG的使用方法,然后看到一个叫做CycleCrackMe的序列号保护练手程序(如图1),刚好是OllyDBG入门文章里面提到的一个演示用程序,只是把OllyDBG的消息断点及RUN的跟踪相关的知识讲了一下,对CycleCrackMe里面具体的加密算法留给读者自己去研究,正好给了我一个练手的机会。

0818b9ca8b590ca3270a3433284dd417.png

(图1)

首先我得把其加密的算法部分剥离出来,通过OllyDBG的动态分析,我把其加密的过程分成了三个函数抽离了出来,分别是:

void ExtendNameTo16Bytes( char *pStrName );

void CalculateKeyStep1( const char *pStrName, const char *pStrSerialNum,

DWORD &outTempNum1, DWORD &outTempNum2 );

bool CalculateKeyStep2( const DWORD nTempNum1, const DWORD nTempNum2,

const char *pStrName, const char *pStrSerialNum );

将抽离的函数实现都抽离出来,容易用C++表示的就用C++逆向出来。得出的实现代码如下:

void ExtendNameTo16Bytes( char *pStrName )

{

assert( NULL != pStrName );

if ( NULL == pStrName ) return;

size_t nStrLen = strlen(pStrName);

int nNeedtoExtend = 16 - nStrLen;

if ( nNeedtoExtend <=0 )

return;

int nCount = 0;

while ( nNeedtoExtend-- )

{

*(pStrName+nStrLen+nCount) = *(pStrName+nCount);

++nCount;

}

}

void CalculateKeyStep1( const char *pStrName, const char *pStrSerialNum,

DWORD &outTempNum1, DWORD &outTempNum2 )

{

assert( NULL != pStrName );

assert( NULL != pStrSerialNum );

if ( NULL == pStrName || NULL == pStrSerialNum )

return;

DWORD nNameTemp1 = *(DWORD*)pStrName;

DWORD nNameTemp2 = *(DWORD*)(pStrName+4);

DWORD nSerialTemp1 = *(DWORD*)pStrSerialNum;

DWORD nSerialTemp2 = *(DWORD*)(pStrSerialNum+4);

nNameTemp1 ^= nSerialTemp1;

nNameTemp2 ^= nSerialTemp2;

nNameTemp1 &= 0x7F3F1F0F;

nNameTemp2 &= 0x7030100;

DWORD nEAX=0;

DWORD nEBX=0;

DWORD nECX=0;

DWORD nEDX=0;

__asm

{

xor ecx, ecx

mov eax, nNameTemp1

mov ebx, nNameTemp2

label3: mov esi, eax ; esi=eax

mov edi, ebx ; edi=ebx

shl esi, cl

shl edi, cl

and esi, 0x80808080 ; esi 与 80808080h

and edi, 0x80808080 ; edi 与 80808080h

mov edx, esi ; edx=esi

shr dh, 7 ; dh,8位右移7位

shl dx, 7

shr edx, 8

shr dh, 7

shl dx, 7

shr edx, 8

shr dh, 7

shr dx, 1

mov esi, edx ; esi=edx

mov edx, edi ; edx=edi

shr dh, 7

shl dx, 7

shr edx, 8

shr dh, 7

shl dx, 7

shr edx, 8

shr dh, 7

shr dx, 5

mov edi, edx ; edi=edx

xor edi, esi ; edi = edi xor edx

mov edx, edi ; edx = edi

and edx, 0x0FF ; edx &= 0xff

push ecx

push edx

mov edx, 8 ; edx=8

xchg eax, ecx

cmp eax, 3

jg short label1

mul dl

pop edx

add eax, 8

xchg eax, ecx

rol eax, cl

xor eax, edx

ror eax, cl

jmp short label2

label1: sub eax, 3

mul dl

pop edx

xchg eax, ecx

rol ebx, cl

xor ebx, edx

ror ebx, cl

label2 :pop ecx

inc ecx ;ecx++

cmp ecx, 8 ;循环8次

jnz label3

mov nEAX, eax

mov nEBX, ebx

}

outTempNum1 = nEAX;

outTempNum2 = nEBX;

}

bool CalculateKeyStep2( const DWORD nTempNum1, const DWORD nTempNum2,

const char *pStrName, const char *pStrSerialNum )

{

DWORD nMagicNum = 0xfedcba98;

__asm

{

mov eax, nTempNum1

mov ebx, nTempNum2

mov ecx, 0xff01

push ecx

call Func

cmp ecx, 1

je label6

jmp label7

Func: pop edi

pop ecx

push edi

cmp ecx, 0x80

jle short label1

push ecx

mov esi, ecx

and ecx, 0xFF

mov edi, eax

cmp ecx, 8

jle short label2

mov edi, ebx

shr ecx, 4

label2: rol edi, 8

shr ecx, 1

jnz short label2

shr esi, 8

and edi, esi

and edi, 0xFF

pop ecx

label4: mov esi, 0x80

label5: test esi, edi

je short label3

xor edi, esi

push edi

and ecx, 0xFF00

xchg esi, ecx

xor ch, cl

xor esi, ecx

xchg ecx, esi

push ecx

inc nMagicNum ;nMagicNum++

call Func

pop edi

jmp short label4

label3: shr esi, 1

jnz short label5

label1: retn

label6: mov eax, DWORD ptr [pStrName+8]

mov ebx, DWORD ptr [pStrName+ 0xc]

xor eax, ebx

xor eax, nMagicNum

or eax, 0x40404040

and eax, 0x77777777

xor eax, DWORD ptr [pStrSerialNum+8]

xor eax, DWORD ptr [pStrSerialNum+0xc]

je label8

label7: xor eax, eax ;符合序列号要求,返回false.

pop edi

pop esi

pop ebx

mov esp, ebp

pop ebp

ret

label8: mov al, 1 ;符合要求返回true.

}

}

算法流程为:首先根据输入的用户名,若不足16字节,则扩展至16字节,然后进入Step1,Step2进行计算判断用户名与序列号是否相配。

To be continued......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值