-
-
160Crackme之02Afkayas.1
-
2022-1-27 12:28 21781
-
师承15PB
课后练习160Crackme之记录篇
02.Afkayas.1
【1】运行exe
双击运行exe,随意输入Name和Serial看结果
结果弹出MessageBox并包含字符串L"You Get Wrong"
【2】进入OD调试
OD打开exe软件并运行至程序入口点;
右键查找字符串找到相关代码
【3】
栈回溯->发现jcc过来的,并非call调用
【4】
爆破点[0040258B]je
【5】
追踪[00402579]test si,si是关键
【6】
往上追踪:si为什么会等于0
【7】
发现字符串:AKA-XXXXXX很诡异;大胆推测:Name或者Serial其中一个
【8】
je往上第一个[00402563]call 进入前si已经为0;
【9】
继续往上一个[00402550]call 进入前si已经为0;
【10】
继续往上一个[00402533]call 进入前si不为0;->探讨为什么si会变成0
【11】
探讨发现,AKA-XXXXX随Name的改变而改变->大胆推测:算法问题,每个账号都有对应的密码,而AKA-XXXXX就是密码->实验证明推理正确
【12】
改变思路:研究如何根据输入的Name计算得出Serial算法
【13】
继续向上最终call,在[004024F4]call 发现异常,指向完此call后EBP-1C存的既然是Serial对应的数字部分
【14】
进入函数查看,发现Serial对应的数字部分早就已经算好了,怎么算的?倒推继续往上找call
【15】
发现[0040243F]call 有问题,call完后真正的Serial对应数字部分出来了,马上跟进去找
【16】
进去第一个call没什么变化(我的做法是先f8过去call看对应的寄存器堆栈内存的变化,如果没变化就看下一个call,知道有我感兴趣的变化,我在进入call);然而第二个[740DBEE3]call有意思,进去看看
【17】
跟踪到[7638E97E]call 进去看看
【18】
跟踪到[7638E941]call 进去看看
【19】
进去后发现[7638E8B3]-[7638E8D3]是生成Serial数字的关键点
【20】
仔细观察后,发现[7638E8BA]的EBP+8的09 E8 0B 00 是重点,要去知道他怎么来的
BE809/A EAX==商;EDX==余数
余数EDX+=30->每次得出的结果是Serial数字的倒序
循环到EAX==0 结束
【21】
EBP+8 [12F3000] 09 E8 0B 00
原来[0012F318]就已经是这个数了
在追踪[0012F3A0]也是这个数
【22】
最终发现[0040243E]处push edi让[0012F3A0]变成09 E8 0B 00的
也就是说追踪EDI的变化
往上查询,发现从[00402415]后开始edi从0开始变化
【23】
edi先==Name的位数 [0040241B]
edi在*0x17CFB [00402420]
然后带符号扩展使得ax(输入Name的第一位)->edx [00402433]
edi在+=edx [00402436]
【24】
此时基本破解,但注意到两个溢出跳转[00402427]和[00402438]
【25】写个VS验证一下?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 插入代码 #include<stdio.h> #include<vector> using std::vector; / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Crackme2 破解 思路:输入Name 获取 Serial * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / int main() { / / 1. 接收Name printf( "输入Name的位数:" ); int Num = 0 ; scanf_s( "%d" , &Num); printf( "输入Name:" ); int Name = 0 ; scanf_s( "%d" , &Name); int SerialNum = 0 ; while (Name / 10 ) { Name / = 10 ; } SerialNum = Num * 0x17CFB ; SerialNum + = (char)Name + 0x30 ; vector< int > Serial; while (SerialNum) { Serial.push_back(SerialNum % 0xA + 0x30 ); SerialNum / = 0xA ; } for ( int i = Serial.size() - 1 ; i > = 0 ; i - - ) { printf( "%d" , Serial[i] - 0x30 ); } return 0 ; } |
AKA-是在je爆破点上方汇编代码最后比较加进去的!!!