0x00 前言

该CrackMe是网络验证。故首先在本地运行Sever端程序:

网络验证Crackme

0x01 发送

首先分析程序发送数据包的内容。于send()函数处设断后,F9运行程序并输入内容:

网络验证Crackme

点击Register按钮,来到断点处:

网络验证Crackme

Ctrl+F9来到主函数:

网络验证Crackme

向上查看,于第二处GetDlgItemText()函数后设断:

网络验证Crackme


打开IDA Pro,从第二处GetDlgItemText()函数后面开始分析:

网络验证Crackme

图中注释详尽,不再赘述。

网络验证Crackme

上图取模运算的判断由优化公式而来:

  • x>=0:x%(2^n) = x&(2^n-1)

  • x<0:x%(2^n) = (x&(2^n-1))-1 | (~(2^n-1))+1

网络验证Crackme

上图红色方框内指令是将Len(Name)Len(Key)Rand()%256依次写入某一处内存区域,名之为SendMes。绿色方框与蓝色方框内指令是将NameKey依次写入到SendMes之后。

网络验证Crackme

根据左边的三处箭头可以判断是for循环,粗略写出C代码如下:

int tmp;    //var_238int KeyLength_NameLength_3;    //Len(Key)+Len(Name)+3int b;char SendMes[];    //Len(Name)+Len(Key)+Rnd(Time)+Name+Keyfor(tmp=0;tmp<KeyLength_NameLength_3;tmp++){    b=SendMes[tmp];    b^=0xA6;    SendMes[tmp]=(b&0xFF);}

由上述分析可以得知发送数据内容,验证之:

网络验证Crackme

0x02 接收

清除之前所设断点,于recv()处设断,F9运行程序并输入内容后点击Register按钮,来到断点。Ctrl+F9来到主函数:

网络验证Crackme

查看缓冲区内容:

网络验证Crackme

既然是加密数据,那么下面一定会有解密操作:

网络验证Crackme

根据上图粗略写出C代码如下:

int tmp;    //var_238char Recv[];    //Data from serverchar Decrypt[]; //0x41AE68for(tmp=0;tmp<Len(Recv);tmp++)"https://s2.ax1x.com/2020/02/21/3KEywT.png" alt="3KEywT.png" />

0X03 判断

网络验证Crackme

上图红色方框中指令处理解密后数据。《加密与解密》随书文件中给出一Python脚本如下:

#coding=utf-8##《加密与解密》第四版##code by DarkNess0utimport osimport sysdef Getasm(ea_from, ea_to, range1, range2):    fp = open("code.txt","w")    ea = ea_from    while ea < ea_to:        cmd = GetMnem(ea)        if cmd == "mov" or cmd == "lea":            opcode = Dword(NextNotTail(ea)-4)            if opcode < 0: #opcode < 0,处理 mov  edx, [ebp-350]指令,否则处理mov  edx, [ebp+350]                opcode = (~opcode + 1)            Message("-> %08X %08X\n" % (ea, opcode))            if range1 <= opcode <= range2:                delta = opcode - range1                MakeComm(ea, "// +0x%04X" % delta) # 加注释到IDA中                fp.write("%08X %s\n" % (ea, GetDisasm(ea)))        ea = NextNotTail(ea)    fp.close()    Message("OK!")Getasm(0x401000,0x40F951,0x41AE68,0x41AEC1);

该脚本功能是将某块指令(该例中为0x401000——0x40F951)内访问指定内存区域(该例中为0x41AE68——0x41AEC1)的指令其后添加注释并拷贝到一TXT中。笔者对其稍加修改如下:

import osimport sysdef Getasm(ea_from, ea_to, range1, range2):    fp = open("E:\\code.txt","w")    ea = ea_from    while ea < ea_to:        cmd = GetMnem(ea)        if cmd == "mov" or cmd == "lea":            opcode = Dword(NextNotTail(ea)-4)            if opcode > 0x7fffffff: #opcode < 0,处理 mov  edx, [ebp-350]指令,否则处理mov  edx, [ebp+350]。原作者此处逻辑虽正确,但判断表达式错误                opcode = 0x100000000-opcode            Message("--> %08X %08X\n" % (ea, opcode))            if range1 <= opcode <= range2:                delta = opcode - range1                fp.write("%08X %s\n" % (ea, GetDisasm(ea)))                MakeComm(ea, "// +0x%04X" % delta) # 加注释到IDA中,注释内容为访问内存相对于起始内存偏移量                ea=NextNotTail(ea)                while ea<ea_to:                    cmd=GetMnem(ea)                    if cmd!="jnz":                        fp.write("%08X %s\n"%(ea,GetDisasm(ea)))                    else:                        break                    ea=NextNotTail(ea)                fp.write("--------------------------------\n")        ea = NextNotTail(ea)    fp.close()    Message("OK!")

Alt+F7执行该脚本,Shift+F2:

网络验证Crackme

TXT内容如下:

网络验证Crackme

负责判断相关指令如上,可根据指令修改相应内存的内容以完成验证。同样可以修改004016BE处指令为EB 63达到目的:

网络验证Crackme

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!