NOP破解
输入姓名,序列号,先输入一个假的看看效果。
好的,注意这串字符串,说明我们的序列号错误,
由程序给的直观的一目,跟输入账号密码一样,一个判断,之后你懂。
载入OD,搜这串字符串,再查看反汇编。
直观可见,上边有一个JNZ跳转,把它NOP,就成功破解了。
序列号生成分析
查看JNZ上边的CALL
发现是一个比较,第一个PUSH是我们输入的序列号,第二个PUSH正确的序列号
那这些数据是从哪里来的呢,继续查看上边的CALL
查看压进去的参数,可以断定这个CALL是生成序列号的,那这些数据又是从哪里来的呢,继续查看上边的操作。
这样的循环操作,就不罗嗦了,直接定位到开始生成的位置。
0042FA79 |> \8D55 F0 lea edx,[local.4]
0042FA7C |. 8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]
0042FA82 |. E8 D1AFFEFF call Acid_bur.0041AA58 ; 获取用户名长度
0042FA87 |. 8B45 F0 mov eax,[local.4] ; 获取用户名首地址
0042FA8A |. 0FB600 movzx eax,byte ptr ds:[eax] ; 获取第一个字符的编码数字
0042FA8D |. F72D 50174300 imul dword ptr ds:[0x431750] ; 将获取的数字乘以29
0042FA93 |. A3 50174300 mov dword ptr ds:[0x431750],eax
0042FA98 |. A1 50174300 mov eax,dword ptr ds:[0x431750]
0042FA9D |. 0105 50174300 add dword ptr ds:[0x431750],eax ; 将乘以后的数据 乘以2
0042FAA3 |. 8D45 FC lea eax,[local.1]
0042FAA6 |. BA ACFB4200 mov edx,Acid_bur.0042FBAC ; CW
0042FAAB |. E8 583CFDFF call Acid_bur.00403708 ; 将CW放在ebp-4位置
0042FAB0 |. 8D45 F8 lea eax,[local.2]
0042FAB3 |. BA B8FB4200 mov edx,Acid_bur.0042FBB8 ; CRACKED
0042FAB8 |. E8 4B3CFDFF call Acid_bur.00403708 ; 将CRACKED放在ebp-8位置
0042FABD |. FF75 FC push [local.1] ; Acid_bur.0042FBAC
0042FAC0 |. 68 C8FB4200 push Acid_bur.0042FBC8 ; -
0042FAC5 |. 8D55 E8 lea edx,[local.6]
0042FAC8 |. A1 50174300 mov eax,dword ptr ds:[0x431750]
0042FACD |. E8 466CFDFF call Acid_bur.00406718 ; 将上边运算的16进制值转换为10进制 然后转成字符串
0042FAD2 |. FF75 E8 push [local.6]
0042FAD5 |. 68 C8FB4200 push Acid_bur.0042FBC8 ; -
0042FADA |. FF75 F8 push [local.2] ; Acid_bur.0042FBB8
0042FADD |. 8D45 F4 lea eax,[local.3]
0042FAE0 |. BA 05000000 mov edx,0x5
0042FAE5 |. E8 C23EFDFF call Acid_bur.004039AC ; 密码生成
0042FAEA |. 8D55 F0 lea edx,[local.4]
0042FAED |. 8B83 E0010000 mov eax,dword ptr ds:[ebx+0x1E0]
0042FAF3 |. E8 60AFFEFF call Acid_bur.0041AA58
0042FAF8 |. 8B55 F0 mov edx,[local.4] ; 输入的密码
0042FAFB |. 8B45 F4 mov eax,[local.3] ; 正确的密码
0042FAFE |. E8 F93EFDFF call Acid_bur.004039FC ; 密码比较
0042FB03 75 1A jnz short Acid_bur.0042FB1F
翻译成的C语言如下:
#include "stdafx.h"int main(int argc, char* argv[])
{char buf[MAX_PATH];printf("请输入用户名(自动生成密码):");scanf("%s", buf);int num = (int)buf[0];num = num * 0x29;num = num * 2;printf("CW-%d-CRACKED\n", num);return 0;
}
多的废话就没有啰嗦了,做这些主要是为了练习反汇编能力。