不用调试,我才是最简单的CrackMe:大道至简
不需要任何分析,你甚至不需要调试器的参与,只要点击“破解”按钮即可破解这个程序。
对于这个程序来说,破解失败比破解成功要困难许多。
那么,你准备好了吗?只要按一下按钮,即可完成任务哦!
如果你不幸破解失败了,那么恭喜你,你解出了完整的题目!
一如既往的,没有壳,没有花指令,只有VS默认的编译优化。
破解成功有什么用? 小白。。。 本帖最后由 solly 于 2020-8-2 02:00 编辑
qzhsjz 发表于 2020-8-1 21:38
有一些问题想请教:
您是怎么做到分析出分了好几个线程跑的逻辑?
直接把这里的eax置0,不会产生另一个 ...
没分析线程,不过可以看到全局变量 ds: 在不停变化,我还以为是定时器。
并且,界面UI的操作,一般是主线程的消息队列来处理的,正常情况不应该出现冲突。
我是通过strcpy()函数特征码找到函数,然后在 IDA 中查看对该函数的调用,稍微看看代码,就确定了这个button的事件函数或其子函数、或其启动的线程调用了这个strcpy(),下个断点,点按钮就断下来了,算运气好吧。因为要修改标签,肯定要调用内存拷贝函数。
特征码是:
74 1C 66 66 66 0F 1F 84 00 00 00 00 00
不要在 strcpy() 下断,调用次数太多。而调用的地方一般很有限,可在调用处一个个试,我刚好是一次试成功。主要是看到了下面这些函数前面的代码可疑:
.text:00000001400045CB loc_1400045CB: ; DATA XREF: .rdata:0000000140B67AC0o
.text:00000001400045CB mov eax, cs:dword_141040A50
.text:00000001400045D1 test eax, eax
.text:00000001400045D3 jnz loc_140004702
.text:00000001400045D9 mov , 89E37834h
.text:00000001400045E0 mov , 600172B6h
.text:00000001400045E7 mov , 7834FF1Ah
.text:00000001400045EE mov , 593189E3h
.text:00000001400045F5 mov , 8D25h
尝试把eax 修成0就看到了你要的效果了。
补充:
后来在IDA中看了那个全局变量的引用,发现是一个随机数,由另一线程调用 c++的 rand()生成的。你设置的关键点在这里吧:
00000001400036A0 | 48:83EC 28 | sub rsp,28 |
00000001400036A4 | E8 2F37AB00 | call 大道至简.140AB6DD8 |
00000001400036A9 | 44:8BC0 | mov r8d,eax |
00000001400036AC | B8 56555555 | mov eax,55555556 |
00000001400036B1 | 41:F7E8 | imul r8d |
00000001400036B4 | 8BCA | mov ecx,edx |
00000001400036B6 | C1E9 1F | shr ecx,1F |
00000001400036B9 | 03D1 | add edx,ecx |
00000001400036BB | 8D0C52 | lea ecx,qword ptr ds: |
00000001400036BE | 44:3BC1 | cmp r8d,ecx |
00000001400036C1 | 74 E1 | je 大道至简.1400036A4 |
00000001400036C3 | E8 1037AB00 | call 大道至简.140AB6DD8 | 这里改成 mov eax, 0
00000001400036C8 | 8905 82D30301 | mov dword ptr ds:,eax |
00000001400036CE | EB D4 | jmp 大道至简.1400036A4 |
只要把 置0就可以了。上面大概是一个死循环:
int var_141040A50 = 0; ///全局变量
void thread_proc() {
while(true) {
int a = rand();
if(a != (a/3)*3) {
var_141040A50 = rand();
}
}
}
关键点在这里:
00000001400045CB | 8B05 7FC40301 | mov eax,dword ptr ds: |
00000001400045D1 | 85C0 | test eax,eax |
00000001400045D3 | 0F85 29010000 | jne 大道至简.140004702 |
eax == 0, 即不跳转,就显示破解失败。 脑洞清奇,小白路过 好一个大道至简。可惜我是小白。 liujiata 发表于 2020-8-1 20:42
好一个大道至简。可惜我是小白。
小白可以点一下破解的,自动破解:lol 学习了,感谢 solly 发表于 2020-8-1 21:22
关键点在这里:
00000001400045CB | 8B05 7FC40301 | mov eax,dword ptr...
有一些问题想请教:
您是怎么做到分析出分了好几个线程跑的逻辑?
直接把这里的eax置0,不会产生另一个线程和这个线程之间对于破解状态那个Label的竞争吗? 求问
小白:我只想知道你是怎么让我的OD附加或者载入都不行的· - ·,这种是怎么解决的?