吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2152|回复: 5
收起左侧

[原创] 练习笔记之160Crackme-023

[复制链接]
xiaoyu2032 发表于 2022-7-2 09:32

160CM-023

1. 爆破

  首先,拖入PE看一下,这是一个“TASM / MASM / FASM - assembler ”编译的程序,百度一下,就是汇编编译器。

  用OD打开程序,搜索一下字符串,关键字都能搜索到,能很快的定位到关键代码段,爆破的话按下图将两处跳转的条件反一下即可。

01.png
  

2. 注册分析

  用IDA打开程序,可以看见这个程序的内容不多,用户函数只有6个,其他都是系统函数。

03.png

  F5依次查看各个函数,过程还比较简单,但是其中有个函数,伪代码很简单,如下图。

int cal_401453()
{
  int v1; // [sp+0h] [bp-4h]@1
  dword_4031A0 = &v1;
  return byte_403166;
}

  但是执行的时候retn后,并不是直接返回到这个函数调用位置的下一行,而是可能跳到==401361==,也可能跳到==40146F==,这个看代码的时候看不大出来,跟踪了好几遍才发现。也就是说401023中有一段代码是该函数执行过程中不会执行的,反而是通过401453进入的。

02.png

  跟踪一下可以发现比较重要的两个就是找到name和serial的存放地址,分别是==40318C==和==403188==。

  然后在关键判断处可以发现,有一处eax与0x10的比较,而跟踪可以发现Serial错误的时候eax只有0xC。

04.png

  查看40149c可以发现,该函数对某个计算结果==+ 152118392==后判断是否为零,为零则将403166加4,而上图中eax的值就是从403166中取出来的,因此关键就是要找到这个计算结果从哪里来的。

int sub_40149C()
{
  int result; // eax@1

  result = dword_403188 + 152118392;
  if ( dword_403188 == -152118392 )
    byte_403166 += 4;
  else
    byte_403166 = 0;
  return result;
}

  跟踪一遍可以发现,==call 401453==执行后,先跳转到==401361==,在里面serial先加1,然后再与name中的四个字节表示的数值进行异或运算,完成后字节地址+1,继续下一次计算,一直到计数值达到0x14。

0040128D  |> \3D 13010000   cmp eax,0x113
00401292  |.  75 50         jnz short Chafe_1.004012E4
00401294  |.  E8 BA010000   call Chafe_1.00401453               ;  转去cal_401453; Case 113 (WM_TIMER) of switch 0040123F

00401453  /$  55            push ebp                                          ;  cal_401453
00401454  |.  8BEC          mov ebp,esp                                       ;  Chafe_1.0040315E
00401456  |.  83C4 FC       add esp,-0x4
00401459  |.  8925 A0314000 mov dword ptr ds:[0x4031A0],esp                   ;  Chafe_1.0040315E
0040145F  |.  8D25 52314000 lea esp,dword ptr ds:[0x403152]
00401465  |.  0FBE05 663140>movsx eax,byte ptr ds:[0x403166]
0040146C  |.  03E0          add esp,eax
0040146E  \.  C3            retn                                             ;  转去401361

00401361   .  8D3D 8C314000 lea edi,dword ptr ds:[0x40318C]                   ;  取name的地址
00401367   .  0FBE05 683140>movsx eax,byte ptr ds:[0x403168]
0040136E   .  03F8          add edi,eax                                       ;  地址++
00401370   .  FE05 68314000 inc byte ptr ds:[0x403168]
00401376   .  A1 88314000   mov eax,dword ptr ds:[0x403188]
0040137B   .  8B25 A0314000 mov esp,dword ptr ds:[0x4031A0]
00401381   .  40            inc eax
00401382   .  FF05 88314000 inc dword ptr ds:[0x403188]                       ;  +1
00401388   .  3307          xor eax,dword ptr ds:[edi]                        ;  异或运算
0040138A   .  A3 88314000   mov dword ptr ds:[0x403188],eax                   
0040138F   .  803D 68314000>cmp byte ptr ds:[0x403168],0x10
00401396   .  75 07         jnz short Chafe_1.0040139F
00401398   .  8005 66314000>add byte ptr ds:[0x403166],0x4                    ;  
0040139F   >  C9            leave
004013A0   .  C3            retn                                              ; 返回401294的下一行

00401299  |.  0FBE05 663140>movsx eax,byte ptr ds:[0x403166]                  ;  1294下一行
004012A0  |.  3A05 67314000 cmp al,byte ptr ds:[0x403167]
004012A6      75 06         jnz short Chafe_1.004012AE
004012A8  |.  33C0          xor eax,eax
004012AA  |.  C9            leave
004012AB  |.  C2 1000       retn 0x10

  根据上述算法,编写计算代码如下:

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <math.h>

int _tmain(int argc, _TCHAR* argv[])
{
    char name[20];
    int sn;
    int temp,length;
    int i, j;
    printf("请输入用户名(长度20以内):");
    scanf_s("%s", name, 20);
    printf("请输入注册码(数字):");
    scanf_s("%d", &sn);
    length = strlen(name);
    j = 0;
    //  正向算法
    for (i = 0; i < 19; i++)
    {
        if (i >= length)
        {
            name[i] = 0;
        }
    }
    for (i = 0; i < 16; i++)
    {
        sn++;
        temp = name[i] + name[i + 1] * 0x100 + name[i + 2] * 0x10000 + name[i + 3] * 0x1000000;
        sn = sn^temp;
        //printf("SN %d为:%d\n", i, sn);
    }

    printf("SN为:%u\n", sn);
    printf("SN为:%0x\n", sn);
    system("pause");
    return 0;
}

  在40149C处设断点,输入任意name和serial,将上述算法计算得到的数值和断点处跟踪到的403188地址的数值进行比较,发现是一致的,说明算法是正确的。

05.png

  要逆推算法, 也就是说要将“0x100000000-0x9112478"的十进制数值(4142848904),通过逆推算法得到serial。正向计算过程是先+1,再异或,逆向算法就是先异或,再-1,因此逆向算法代码如下:

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <math.h>

int _tmain(int argc, _TCHAR* argv[])
{
    char name[20];
    int sn;
    int temp,temp2,length;
    int i, j;
    printf("请输入用户名(长度20以内):");
    scanf_s("%s", name, 20);
    printf("请输入注册码(数字):");
    scanf_s("%d", &sn);
    length = strlen(name);
    j = 0;
    // 逆向算法
    for (i = 0; i < 19; i++)
    {
        if (i >= length)
        {
            name[i] = 0;
        }
    }
    for (i = 15; i >=0; i--)
    {

        temp = name[i] + name[i + 1] * 0x100 + name[i + 2] * 0x10000 + name[i + 3] * 0x1000000;
        sn = sn^temp;
        sn--;
        //printf("SN %d为:%u\n", i, sn);
    }
    printf("SN为:%u\n", sn);
    printf("SN为:%0x\n", sn);
    system("pause");
    return 0;
}

  这里需要注意的是由于程序中输入负数会识别成零,因此需要用无符号整型来显示结果。输入用户名==abcde==,SN输入==4142848904==,计算结果如下:

06.png

  运行程序,分别输入abcde和4153203471,注册成功!

07.png

3. 总结

  这个程序里面比较难分析的就是函数401023中有一段代码是从其他函数进入的,实现方式好像是通过在retn前将esp加不同的值实现的,这个大大增加了分析难度,我只能通过动态跟踪来确定执行过程。如果这个程序复杂一些,再对字符串进行加密处理,感觉很可能就找不到地方了。

免费评分

参与人数 5威望 +1 吾爱币 +23 热心值 +5 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
4nfu + 1 我很赞同!
p52p + 1 + 1 我很赞同!
唐小样儿 + 1 + 1 我很赞同!
woflant + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Panel 发表于 2022-7-2 13:53
这个算法其实看起来相对来说是比较简单的
p52p 发表于 2022-7-2 17:15
Junlee 发表于 2022-7-2 20:52
kanxue2018 发表于 2022-7-3 08:56
好好学习,认真总结
冥界3大法王 发表于 2022-7-4 08:07
image.png
谢谢你的ida分析。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 00:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表