[软件名称] : PDFPassword Remover
[编译类型] : VC++
[是否有壳] : 无壳
[注册类型] : 注册码注册
[作者信息] : LYQingYe
//算法CALL查找方法,字符串搜索 或者 bp MessageBoxA -> 算法CALL sub_00406E30
//进入算法CALL,先看校验准备部分
[Asm] 纯文本查看 复制代码 //初始化局部变量
00406E48 |>sub esp,0x40 ;
//获取传入的参数[arg.1],key的指针 pkey
00406E4B |>push esi ; winDecry.004CDD8A
00406E4C |>mov eax,[arg.1] ; lea eax,key
00406E4F |>push eax ; push pkey
00406E50 |>lea ecx,[local.11] ; this指针也就是CString对象指针 local.11存放函数返回值
//复制传入得pkey参数,返回值给 [local.11] -> 将新复制得CString 命名为 Key
00406E53 |>call winDecry.004CD6F3 ; NewCString(&local.11,pkey);
// Key检查,通过搜索Key字符串中是否0x20 字符,如果存在则非法
[Asm] 纯文本查看 复制代码 00406E58 |>mov [local.1],0x0 ; local.1 = 0;
00406E5F |>push 0x20 ; 要搜索的字符 0x20
00406E61 |>lea ecx,[local.11] ; CString对象指针 -> Key
//搜索Key中是否存在0x20字符,若存在则销毁Key字符串,从而失败
00406E64 |>call winDecry.004C49A1 ; FindCString(&Key,0x20);
//获取CString Key 对象指向的字符串缓冲区
[Asm] 纯文本查看 复制代码 00406E69 |>lea ecx,[local.11] ; CString对象指针 -> Key
// Key->StrBuffer
00406E6C |>call winDecry.00401E50 ; GetCStringBuffer(&Key)
//获取Key的长度
[Asm] 纯文本查看 复制代码 00406E71 |>mov [local.4],eax ; eax -> StrBuffer
00406E74 |>mov ecx,[local.4] ; local.4 = Strbuffer
00406E77 |>push ecx
//测量字符串长度 [Asm] 纯文本查看 复制代码 00406E78 |>call winDecry.004AB840 ; Strlen(StrBuffer)[/align]
00406E7D |>add esp,0x4
00406E80 |>cmp eax,0x14 ;判断字符串长度是否等于0x14,也就是20位,如若不等则失败
00406E83 |>je short winDecry.00406EA3
//下面开始校验Key
//第一部分,校验输入的数字Key的 第一位 + 第二位要等于13,否则失败
[Asm] 纯文本查看 复制代码 00406EA3 |>mov edx,[local.4] ;Local.4 ->StrBuffer
00406EA6 |>mov al,byte ptr ds:[edx] ;获取Key的第一位ASCII值
00406EA8 |>mov byte ptr ss:[ebp-0x1C],al ;存放到局部变量 [ebp-0x1C]
00406EAB |>mov byte ptr ss:[ebp-0x1B],0x0 ;初始化局部变量 [ebp-0x1B]
00406EAF |>mov ecx,[local.4] ;Local.4 ->StrBuffer
00406EB2 |>mov dl,byte ptr ds:[ecx+0x1] ;获取Key第二位ASCII值
00406EB5 |>mov byte ptr ss:[ebp-0x28],dl ;存放到局部变量 [ebp-0x28]
00406EB8 |>mov byte ptr ss:[ebp-0x27],0x0
00406EBC |>lea eax,[local.7] ;
00406EBF |>push eax ;压入刚才获取得Key的第一位 ASCII
00406EC0 |>call winDecry.004AC590 ;将ASCII 转换为 整数
00406EC5 |>add esp,0x4
00406EC8 |>mov esi,eax ;ESI = Key的第一位数值
00406ECA |>lea ecx,[local.10] ;
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 ,不等则失败
[Asm] 纯文本查看 复制代码 //第二部分,校验输入的数字Key的 第19位 + 第20位要等于13,否则失败
00406EFB |>>mov edx,[local.4] ;EDX -> StrBuffer
00406EFE |.>mov al,byte ptr ds:[edx+0x12] ;local.7 = StrBuffer [19]
00406F01 |.>mov byte ptr ss:[ebp-0x1C],al
00406F04 |.>mov byte ptr ss:[ebp-0x1B],0x0
00406F08 |.>mov ecx,[local.4]
00406F0B |.>mov dl,byte ptr ds:[ecx+0x13] ;local.10 = StrBuffer[20]
00406F0E |.>mov byte ptr ss:[ebp-0x28],dl
00406F11 |.>mov byte ptr ss:[ebp-0x27],0x0
00406F15 |.>lea eax,[local.7] ;压入Key第19位
00406F18 |.>push eax
[Asm] 纯文本查看 复制代码 00406F19 |.>call winDecry.004AC590 ;转换为整数
00406F1E |.>add esp,0x4
00406F21 |.>mov esi,eax
00406F23 |.>lea ecx,[local.10]
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,否则失败,和上面一样,不再过多阐述
[Asm] 纯文本查看 复制代码 00406F54 |>>mov edx,[local.4]
00406F57 |.>mov al,byte ptr ds:[edx+0x5] ;StrBuffer[6]
00406F5A |.>mov byte ptr ss:[ebp-0x1C],al
00406F5D |.>mov byte ptr ss:[ebp-0x1B],0x0
00406F61 |.>mov ecx,[local.4]
00406F64 |.>mov dl,byte ptr ds:[ecx+0xD] ;StrBuffer[13]
00406F67 |.>mov byte ptr ss:[ebp-0x28],dl
00406F6A |.>mov byte ptr ss:[ebp-0x27],0x0
00406F6E |.>lea eax,[local.7]
00406F71 |.>push eax
00406F72 |.>call winDecry.004AC590 ;字符转化为整数
00406F77 |.>add esp,0x4
00406F7A |.>mov esi,eax
00406F7C |.>lea ecx,[local.10]
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
//最后零散校验
[Asm] 纯文本查看 复制代码 //判断第13位是否等于0x35 ->> '5'
00406FAD |> \8B55 F0 mov edx,[local.4]
00406FB0 |. 0FBE42 0C movsx eax,byte ptr ds:[edx+0xC] ;StrBuffer [12]
00406FB4 |. 83F8 35 cmp eax,0x35
00406FB7 |. 74 1B je short winDecry.00406FD4
//判断第15位是否等于0x56 ->> 'V'
00406FD4 |> \8B4D F0 mov ecx,[local.4]
00406FD7 |. 0FBE51 0E movsx edx,byte ptr ds:[ecx+0xE] ;StrBuffer[14]
00406FDB |. 83FA 56 cmp edx,0x56
00406FDE |. 74 1B je short winDecry.00406FFB
//判断第16位是否等于0x50 ->> 'P'
00406FFB |> \8B45 F0 mov eax,[local.4]
00406FFE |. 0FBE48 0F movsx ecx,byte ptr ds:[eax+0xF] ;StrBuffer[15]
00407002 |. 83F9 50 cmp ecx,0x50
00407005 |. 74 1B je short winDecry.00407022
//以上就是算法部分,下面总结, Key第1位+第2位加起来要为13 Key第19位+第20位加起来要为13 Key第6位+第14位加起来要为13
Key第13位ACSII是否等于0x35 ->> '5' Key第15位ASCII是否等于0x56 ->> 'V' Key第16位ASCII是否等于0x50 ->>'P'
//下面是逆向整理后的伪算法 -> C/C++
//尊重作者,就不放keygen.
|