新160个CrackMe039-eKH.1、040-DaNiEl-RJ.1、041-genocide1逆向分析 039无壳暴力破解找到关键跳转将其改成jmp即可获取破解版本算法分析先获取用户名和序列号之后经过一个函数将函数返回值与0xBC614E十进制数是12345678进行对比相等则成功步进分析函数ekh.1.427A20进行一个循环先是每次都获取用户输入的用户名再将它逻辑左移八位之后从一个固定字符串中取出当前用户名字符串下标对应的固定字符串中的字符将他与逻辑左移后的数进行异或之后将获取的字符串从十六进制转换成十进制并且获取计算之后的字符串长度进行下一个循环将获得的整数除0xA求出的余数作为下标从新的系统自带的字符串中其提出相应的字符经过n次循环之后获取正确的序列号可以生成keygen:username input(Input username:).strip() sum_val 0 a LANNYDIBANDINGINANAKEKHYANGNGENTOT b LANNY5646521 len_a len(a) b_len len(b) for i, ch in enumerate(username): sum_val ord(ch) sum_val (sum_val 8) 0xFFFFFFFF index a[i] if i len_a else a[i % len_a] sum_val (sum_val | ord(index)) 0xFFFFFFFF if sum_val 0x80000000: sum_val (0x100000000 - sum_val) 0xFFFFFFFF sum_val (sum_val ^ 0x12345678) 0xFFFFFFFF print(fsum: {sum_val}) print(fHex: 0x{sum_val:08X}) index temp sum_val while temp 0: idx temp % 0xA idx idx % b_len char b[idx] index char temp temp // 0xA print(findex: {index})040无壳直接点开程序没办法进入到到验证页面要先点下面的about关闭弹窗之后才可以继续点击注册页面暴力破解发现关键跳转将其给nop掉即可获取破解版本算法分析经过一个循环将用户名的每一个字符ASCII码值5再转换成字符拼接起来生成的新的字符串就是生成的序列号可以生成keygen:usernameinput(Input username:).strip() serial for ch in username: charchr(ord(ch)5) serialchar print(fSerial:{serial})041UPX壳脱壳直接点开程序发现只有一个弹窗将该弹窗关掉之后程序自动退出解开程序从这里看到程序会验证是否存在Reg.dat文件如果存在就不会出现弹窗将该跳转给改成jmp即可解开程序让程序成功正常运行输入序列号和用户名发现没办法点击确认按钮初步推测是在序列号部分实时验证是否正确来决定确认按钮是否可以点击算法分析先用PE Explorer来分析整个程序可以观察到TForm2是关于输入用户名和序列号的那个窗体TForm3是关于about窗体TForm2下的Edit1Change、Edit2Change和下面的34分别对应了注册窗体的四个序列号在IDA中可以找到相关函数的地址分别是437E70、437E7C、437E88、437E94在相关位置下断点进入函数发现有四个跳转每个跳转都跳转到调用函数的位置期间没有进行运算继续进入函数发现函数437BD8内有运算在该函数内下断点方便后续动态调试运行打开注册窗口发现在用户名和序列号输入之前就断下了点了四次运行才成功看到注册窗口输入用户名之后调试序列号发现没有变化需要继续点击运行直到前三位序列号都正常显示调试第四位序列号时不运行开始步过观察发现对输入的第1、3、4、5位对0xA求商存到指定位置之后又经过了一个循环检验获取的每一位序列号是否大于9如果是则重新对0xA取商覆盖原来的值接下来将通过用户名获取的序列号与用户输入的序列号进行对比不相等就跳转失败可以得到keygen:usernameinput(Input username:).strip() serial for i,ch in enumerate(username): if i1: continue if i5: break tempord(ch)//0xA while temp0xA: temptemp//0xA serialchr(temp48) print(fSerial:{serial})暴力破解根据前面的分析可以得出将地址处的跳转给nop掉即可获得破解版本程序