LYQingYe 发表于 2016-8-1 09:34

PDFPasswordRemover 算法分析逆向

[软件名称]:PDFPassword Remover
[编译类型]:VC++
[是否有壳]:无壳
[注册类型]:注册码注册
[作者信息]:LYQingYe
//算法CALL查找方法,字符串搜索或者 bp MessageBoxA -> 算法CALLsub_00406E30


//进入算法CALL,先看校验准备部分
//初始化局部变量
00406E48|>sub esp,0x40      ;

//获取传入的参数,key的指针 pkey
00406E4B|>push esi                                 ;winDecry.004CDD8A
00406E4C|>mov eax,                        ;lea eax,key
00406E4F|>push eax                                 ;push pkey
00406E50|>lea ecx,                                 ; this指针也就是CString对象指针local.11存放函数返回值
//复制传入得pkey参数,返回值给 -> 将新复制得CString 命名为 Key
00406E53|>call winDecry.004CD6F3                   ;NewCString(&local.11,pkey);

// Key检查,通过搜索Key字符串中是否0x20 字符,如果存在则非法
00406E58|>mov ,0x0                                 ; local.1 = 0;
00406E5F|>push 0x20                                       ; 要搜索的字符 0x20
00406E61|>lea ecx,                                 ; CString对象指针 -> Key
//搜索Key中是否存在0x20字符,若存在则销毁Key字符串,从而失败
00406E64|>call winDecry.004C49A1                   ;FindCString(&Key,0x20);

//获取CString Key 对象指向的字符串缓冲区
00406E69|>lea ecx,                                 ; CString对象指针 -> Key
// Key->StrBuffer
00406E6C|>call winDecry.00401E50                   ;GetCStringBuffer(&Key)

//获取Key的长度
00406E71|>mov ,eax                        ; eax -> StrBuffer
00406E74|>mov ecx,                              ; local.4 = Strbuffer
00406E77|>push ecx

//测量字符串长度00406E78|>call winDecry.004AB840                   ;Strlen(StrBuffer)
00406E7D|>add esp,0x4
00406E80|>cmp eax,0x14                                        ;判断字符串长度是否等于0x14,也就是20位,如若不等则失败
00406E83|>je short winDecry.00406EA3


//下面开始校验Key
//第一部分,校验输入的数字Key的 第一位 + 第二位要等于13,否则失败
00406EA3|>mov edx,                              ;Local.4 ->StrBuffer
00406EA6|>mov al,byte ptr ds:                     ;获取Key的第一位ASCII值
00406EA8|>mov byte ptr ss:,al            ;存放到局部变量
00406EAB|>mov byte ptr ss:,0x0         ;初始化局部变量
00406EAF|>mov ecx,                              ;Local.4 ->StrBuffer
00406EB2|>mov dl,byte ptr ds:                ;获取Key第二位ASCII值
00406EB5|>mov byte ptr ss:,dl                ;存放到局部变量
00406EB8|>mov byte ptr ss:,0x0
00406EBC|>lea eax,                              ;
00406EBF|>push eax                                        ;压入刚才获取得Key的第一位 ASCII
00406EC0|>call winDecry.004AC590                        ;将ASCII 转换为 整数
00406EC5|>add esp,0x4
00406EC8|>mov esi,eax                                        ;ESI = Key的第一位数值
00406ECA|>lea ecx,                              ;
00406ECD|>push ecx                                        ;压入刚才获得Key的第二位 ASCII
00406ECE|>call winDecry.004AC590                        ;将ASCII 转换为 整数      
00406ED3|>add esp,0x4               
00406ED6|>add esi,eax                                        ; 数字Key的 第一位 + 第二位 相加
00406ED8|>cmp esi,0xD      
00406EDB|>je short winDecry.00406EFB               ; 判断 第一位 + 第二位 == 13 ,不等则失败


//第二部分,校验输入的数字Key的 第19位 + 第20位要等于13,否则失败

00406EFB|>>mov edx,                              ;EDX -> StrBuffer
00406EFE|.>mov al,byte ptr ds:                ;local.7 = StrBuffer
00406F01|.>mov byte ptr ss:,al
00406F04|.>mov byte ptr ss:,0x0
00406F08|.>mov ecx,
00406F0B|.>mov dl,byte ptr ds:                ;local.10 = StrBuffer

00406F0E|.>mov byte ptr ss:,dl
00406F11|.>mov byte ptr ss:,0x0
00406F15|.>lea eax,                              ;压入Key第19位
00406F18|.>push eax

00406F19|.>call winDecry.004AC590                        ;转换为整数
00406F1E|.>add esp,0x4
00406F21|.>mov esi,eax

00406F23|.>lea ecx,
00406F26|.>push ecx                                        ;压入Key第20位
00406F27|.>call winDecry.004AC590                        ;转换为整数
00406F2C|.>add esp,0x4
00406F2F|.>add esi,eax                                        ;第19位 + 第20位
00406F31|.>cmp esi,0xD                                        ;判断第19位 + 第20位 是否等于13,不等则失败

//第三部分,校验输入的数字Key的 第6位 + 第14位要等于11,否则失败,和上面一样,不再过多阐述
00406F54|>>mov edx,               
00406F57|.>mov al,byte ptr ds:                ;StrBuffer
00406F5A|.>mov byte ptr ss:,al
00406F5D|.>mov byte ptr ss:,0x0
00406F61|.>mov ecx,
00406F64|.>mov dl,byte ptr ds:                ;StrBuffer
00406F67|.>mov byte ptr ss:,dl
00406F6A|.>mov byte ptr ss:,0x0
00406F6E|.>lea eax,
00406F71|.>push eax
00406F72|.>call winDecry.004AC590                        ;字符转化为整数
00406F77|.>add esp,0x4
00406F7A|.>mov esi,eax
00406F7C|.>lea ecx,
00406F7F|.>push ecx
00406F80|.>call winDecry.004AC590                     ;字符转化为整数
00406F85|.>add esp,0x4
00406F88|.>add esi,eax
00406F8A|.>cmp esi,0xB                                        ; 第6位 + 第14位要等于11,否则失败
00406F8D|.>je short winDecry.00406FAD

//最后零散校验
//判断第13位是否等于0x35->> '5'
00406FAD|> \8B55 F0          mov edx,
00406FB0|.0FBE42 0C      movsx eax,byte ptr ds:;StrBuffer
00406FB4|.83F8 35          cmp eax,0x35
00406FB7|.74 1B            je short winDecry.00406FD4

//判断第15位是否等于0x56->> 'V'
00406FD4|> \8B4D F0          mov ecx,
00406FD7|.0FBE51 0E      movsx edx,byte ptr ds:                ;StrBuffer
00406FDB|.83FA 56          cmp edx,0x56
00406FDE|.74 1B            je short winDecry.00406FFB

//判断第16位是否等于0x50 ->> 'P'
00406FFB|> \8B45 F0          mov eax,
00406FFE|.0FBE48 0F      movsx ecx,byte ptr ds:                ;StrBuffer
00407002|.83F9 50          cmp ecx,0x50
00407005|.74 1B            je short winDecry.00407022



//以上就是算法部分,下面总结,Key第1位+第2位加起来要为13 Key第19位+第20位加起来要为13Key第6位+第14位加起来要为13
Key第13位ACSII是否等于0x35->> '5'Key第15位ASCII是否等于0x56->> 'V'Key第16位ASCII是否等于0x50 ->>'P'

//下面是逆向整理后的伪算法 -> C/C++
**** Hidden Message *****

//尊重作者,就不放keygen.



Shark恒 发表于 2016-8-1 12:29

支持算法分析,感谢LYQingYe!

Rooking 发表于 2016-8-1 13:43

前排膜拜一下 算法帝

泪落尘埃 发表于 2016-8-5 11:26

前来学习!

jiajiayu 发表于 2016-8-6 09:11

膜拜大牛;跟大牛学习一下算法

610100 发表于 2016-8-6 16:05

谢谢楼主。

云空晴上 发表于 2016-8-6 17:54

Bu弃 发表于 2016-8-6 17:59

算法牛。我服

vov369 发表于 2016-8-7 21:17

谢谢分享,

DDK4282 发表于 2016-8-9 23:34

感谢分享思路!
页: [1] 2 3 4 5
查看完整版本: PDFPasswordRemover 算法分析逆向