g2uc

TeamBlog

[160个CrackMe学习系列]CrackMe.23-Chafe.1

0x01 程序分析正文

拿到程序后先查壳:

可以看到,没有壳子,所以直接开始分析,本次我选择的是全程使用od动态调试.

然后我们先运行下程序看看是大概怎样的程序.

可以看到就是一个name/serial型的程序,不过成功的提示应该会在Status编辑框里显示,并不会有MessageBox提示,这一点应该也是为了防止下断

程序载入OD后先搜索一下字符串:

可以看到成功提示的字,跳过去看一下

可以发现非常明显的成功失败判断的跳转,在该关键跳转处下断后,可以发现程序是一直被断下的,说明他的验证函数是被循环执行的,可能是创建了一个时钟进行循环验证.

此外还能发现,serial输入纯数字才能触发验证判断,否则是不会在关键跳处断下,这说明很可能是验证函数中serial被作为纯数字来进行运算.

图中可看出,最终被判断的是eax是否为0x10,而eax的值来源于byte ptr [0x403166],这个地址很可能是一个global var.因此接下来的思路就是寻找是什么地方在修改这个变量

那么就在0x403166处下个内存断点看看:

以下是断下的三个位置:

由此我们可以看出程序中每次都是给这个变量+4,那么需要加到0x10还差一次,那来试试在程序中搜索(Ctrl+F)这条汇编命令,按Ctrl+L可以跳到下一个搜索结果

啊哈!果不其然,的确有第四条指令,而且这条上面有一个jnz的跳转,如果跳成功就是执行下面把0x403166置0的操作,否则就是执行+4操作

而jnz跳转上面的test eax,eax 其实就是判断eax是否为0,若为0则不跳转jnz,再往上看,是把另一个疑似global var的[0x403188]赋值给eax,然后eax+0x9112478

后面判断eax是否为零.

因此要想这里的第四条+4指令执行,则[0x403188]里的值必须是-0x9112478,在内存中,则是(0xFFFFFFFF-0x9112478+1)=0xF6EEDB88(好像是补码?大概)

因此现在我们要再次使用刚才的套路,内存下断看看[0x403188]在哪里被written,这里特别说一点就是这里的下断是下4个字节,因为上图中运算的长度是4字节.

最终断下了三个地址:

并且根据对该指针的监视我们可以知道,在程序走到0x401488时,[0x403188]的内容是一开始在serial输入的”1234”的hex格式0x000004D2,对上图代码下断走了一遍发现
00401361 . 8D3D 8C314000 lea edi, dword ptr [0x40318C]
也就是说这里可能就是核心算法,计算了name和serial得出结果存放到[0x403188],若结果是0xF6EEDB88,验证就会成功!

接下来分析下这里算法的具体步骤:

如上文所述:这部分的代码会被循环4次,每次[0x40318C]的内容会后移1字节

经过多次的单步运行,查看指针指向的内容后可知,总共会把name分成16部分,因此需循环16次,每部分4字节,name最大长度是16,超过的字符应该是不影响

如果name不足16字节,则不足的部分由0x00来代替.

接下来直接从jmp跳下面开始分析:

00401361 . 8D3D 8C314000 lea edi, dword ptr [0x40318C] ; 此处是把name的指针赋值给edi
00401367 . 0FBE05 683140>movsx eax, byte ptr [0x403168] ; 将[0x403168]内容赋值给eax,这里的内容是计次的变量
0040136E . 03F8 add edi, eax ; 根据计次变量移动edi指针,实现每次循环四个字节向右移一位
00401370 . FE05 68314000 inc byte ptr [0x403168] ; 计次变量+=1
00401376 . A1 88314000 mov eax, dword ptr [0x403188] ; 将[0x403188]的内容赋值给eax,这里初始值是输入的serial的int格式,例如输入"1234"则是0x000004D2 (HEX:D2 04 00 00)
0040137B . 8B25 A0314000 mov esp, dword ptr [0x4031A0] ; esp指向变化,这里应该是和他循环有关但是和算法内容无关,所以可以忽略
00401381 . 40 inc eax ; eax 中的内容自增1
00401382 . FF05 88314000 inc dword ptr [0x403188] ; [0x403188]的内容自增1,此时eax和[0x403188]内容相等
00401388 . 3307 xor eax, dword ptr [edi] ; 四个字节转成int后与eax异或,结果保存在eax
0040138A . A3 88314000 mov dword ptr [0x403188], eax ; 把eax的结果赋值给[0x403188]
0040138F . 803D 68314000>cmp byte ptr [0x403168], 0x10 ; 判断计次变量是否循环到16,若是则跳出循环
00401396 . 75 07 jnz short 0040139F ; 跳转,跳出循环
00401398 . 8005 66314000>add byte ptr [0x403166], 0x4 ; 3

经过以上循环后,如果[0x403188]的内容是0xF6EEDB88则验证成功,因此我们只要写出逆向的循环解密即可!

易语言代码如下:

serial_int = 4142848904' 此处是0xF6EEDB88

.计次循环首 (16, i)

    name_i = 到字节集 (取文本中间 (name, 17 - i, 4)) '这里是取出4字节

    name_i = name_i + 取空白字节集 (4 - 取字节集长度 (name_i))'这里是name不足则补齐0x00

    name_site = 取字节集数据 (到字节集 (name_i), #长整数型, )'将四字节转成长整数,以便下面异或运算

    serial_int = xor64 (serial_int, name_site)'这里用的异或非易语言原生异或,原生异或不支持4字节长整数

    serial_int = serial_int - 1

.计次循环尾 ()

调试输出 (serial_int)


成功计算出正确Serial

发表评论:

搜索
标签列表
网站分类
文章归档
站点信息
  • 文章总数:20
  • 页面总数:0
  • 分类总数:4
  • 标签总数:7
  • 评论总数:1
  • 浏览总数:566
控制面板
您好,欢迎到访网站!
  查看权限

Powered By Z-BlogPHP 1.5.2 Zero

Copyright g2uc Rights Reserved.

公告

请把不属于分类中比赛的题目wp发布在essay分类!另外,题解文章请记得在标签里标注题目类型!