zoukankan      html  css  js  c++  java
  • 看雪论坛 破解exe 看雪CTF2017第一题分析-『CrackMe』-看雪安全论坛

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha

    逆向 黑客 破解 学习 论坛

    『CrackMe』

    http://bbs.pediy.com/thread-218199.htm

    [原创][原创]看雪CTF2017第一题分析-『CrackMe』-看雪安全论坛

    IDA 

    交互式反汇编器专业版(Interactive Disassembler Professional),人们常称其为IDA Pro,或简称为IDA,是总部位于比利时列日市(Liège)的Hex-Rayd公司的一款产品。开发IDA的是一位编程天才,名叫Ilfak Guilfanov。十年前诞生时,IDA还是一个基于控制台的MS-DOS应用程序,这一点很重要,因为它有助于我们理解IDA用户界面的本质。除其他内容外,IDA的非Windows和非GUI版本仍然继续采用源于最初DOS版本的控制台形式的界面。
    就其本质而言,IDA是一种递归下降反汇编器。但是,为了提高递归下降过程的效率,IDA的开发者付出了巨大的努力,来为这个过程开发逻辑。为了克服递归下降的一个最大的缺点,IDA在区分数据与代码的同时,还设法确定这些数据的类型。虽然你在IDA中看到的是汇编语言形式的代码,但IDA的主要目标之一,在于呈现尽可能接近源代码的代码。此外,IDA不仅使用数据类型信息,而且通过派生的变量和函数名称来尽其所能地注释生成的反汇编代码。这些注释将原始十六进制代码的数量减到最少,并显著增加了向用户提供的符号化信息的数量。
    IDA PRO简称IDA(Interactive Disassembler) ,是一个世界顶级的交互式反汇编工具,有两种可用版本。标准版(Standard)支持二十多种处理器。高级版(Advanced)支持50多种处理器。


    =====

    一道普通的CrackMe,Windows 32位程序,无壳、无VM、无密码学的三无CrackMe,祝大家六一laugh Out Loud。
    由于严重多解,联系作者限制了一下多解(原来的提交仍有效),欢迎大家积极参加。

    请提交分析文章(writeup)至:http://bbs.pediy.com/thread-create-122.htm

    
    文件地址:
    ========

    找到文本输入点
        输入“123456”可以看到“error!”的错误提示。

        在OD中正好可以查找到“error!”字符串。

        定位到调用“Messagebox”函数的位置。

        上推到“GetDlgItemTextA”函数即为文本输入点。

    2、分析数据处理过程
        由文本输入点往下跟踪输入文本的处理,大概如下:
        首先判断输入文本长度是否为“0x4”,若不是则跳转到错误提示。 cmp 就是比较的意思。 jnz 是 如果不相等 跳转到。

        

        其次判断每个字符ASCII码是否为“0x30”(48)即数字0,若是则跳转到错误提示,之后判断第一二个字符是否分别为“0x31”(49)和“0x35”(53)即数字1和5,若不是则跳转到错误提示。

    je是 如果相等,跳转到。    绿色字符 是变量。 白色 是 一个跳转地址。 黄色是 某种方法。 深蓝色 是 栈的进出,push是进栈,pop是出栈。  褐色 是 常量。 

        

        然后对四个字符进行计算,将第三四个字符表示为x和y,同时将16进制数字转换为10进制,则过程得到的结果为[(x-48)-(49-48)/(53-48)]*(y-48)*16

    1C,1B,1A,19  是1到4位的对应号。   f开头是 浮点数。 mul 是乘以。 fild是将整数转化为长双精FP80压栈。fidiv 浮点除整数。fimul浮点乘整数。fmul浮点乘。fstp浮点保存出栈。

    可以百度查 汇编指令。 mov 传送,movsx符号传送。sub 减。

        最后与ds:[0x407118]中的常数384比较,若相同则弹出“Registration successful!”的正确提示。

    3、解出注册码
        根据计算过程求出方程:
        [(x-48)-(49-48)/(53-48)]*(y-48)*16=384
    x和y在可输入ASCII码范围内的整数解即可,则可如下求解

    1
    2
    3
    4
    5
    6
    7
        for in range(126):
        for in range(126):
            if(((i-48)-0.2)*(j-48== 24):
                print(i)
                print(j)
                print("15"+"%s"%(chr(i))+"%s"%(chr(j)))
                print("------")

        解得:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    47
    28
    15/
    ----
    49
    78
    151N
    ----
    53
    53
    1555
    ----

        其中第一个的ASCII码”28“为文件分割符,注册码则为“151N”和“1555”。

    ==========

     

    使用环境

    备注

    操作系统

    Windows xp

    简体中文版

    虚拟机

    VMware Workstation

    版本号:12.1.1 build

    调试器

    Immunity Debugger

    版本号:V1.73

    调试器             

    IDA

    版本号:V6.5.140116

    0x02 分析调试过程

    用ImmunityDebugger打开WannaLOL2.exe,F9执行,经过几次试探输入,初步定位0x00401494处的CALL WannaLOL.00401096为调用验证序列号的主函数,在此按F2下断点。

    再次运行,按F9运行到断点处,按F7单步进入00401096函数。在获取输入对话框内容的GetDlgItemTextA函数处下断点。再次运行,输入试探序列号后,程序执行到0x0040120B。

    通过分析和调试得知,WannaLOL.00401300函数返回输入序列号的长度。

    通过IDA静态分析,以下代码为确定序列号长度及特殊要求的关键代码:

    .text:00401225                 cmp     eax, 4

    .text:00401228                 pop     ecx

    .text:00401229                 jnz     loc_4012CF

    .text:0040122F                 push    30h

    .text:00401231                 pop     ecx

    .text:00401232                 cmp     [ebp-1Ch], cl

    .text:00401235                 jz      loc_4012CF

    .text:0040123B                 cmp     [ebp-1Bh], cl

    .text:0040123E                 jz      loc_4012CF

    .text:00401244                 cmp     [ebp-1Ah], cl

    .text:00401247                 jz      loc_4012CF

    .text:0040124D                 cmp     [ebp-19h], cl

    .text:00401250                 jz      short loc_4012CF

    .text:00401252                 cmp     byte ptr [ebp-1Ch], 31h

    .text:00401256                 jnz     short loc_4012CF

    .text:00401258                 cmp     byte ptr [ebp-1Bh], 35h

    .text:0040125C                 jnz     short loc_4012CF

    .text:0040125E                 jz      short near ptr loc_401262+1

    .text:00401260                 jnz     short near ptr loc_401262+1

    通过调试和分析得知,序列号长度为4位,不能包含0,第一位必须为1,第二位必须为5,即15s(3)s(4)( s(n)为序列号第n位,s(3)!=0, s(4)!=0)。紧接下来的代码为浮点运算代码:

    .text:00401267                 xor     ax, 7

    .text:0040126B                 movsx   eax, byte ptr [ebp-1Ah]

    .text:0040126F                 sub     eax, ecx

    .text:00401271                 mov     [ebp-4], eax

    .text:00401274                 movsx   eax, byte ptr [ebp-1Ch]

    .text:00401278                 fild    dword ptr [ebp-4]

    .text:0040127B                 sub     eax, ecx

    .text:0040127D                 mov     [ebp-4], eax

    .text:00401280                 movsx   eax, byte ptr [ebp-1Bh]

    .text:00401284                 fild    dword ptr [ebp-4]

    .text:00401287                 sub     eax, ecx

    .text:00401289                 mov     [ebp-4], eax

    .text:0040128C                 fidiv   dword ptr [ebp-4]

    .text:0040128F                 movsx   eax, byte ptr [ebp-19h]

    .text:00401293                 sub     eax, ecx

    .text:00401295                 mov     [ebp-4], eax

    .text:00401298                 fsubp   st(1), st

    .text:0040129A                 fimul   dword ptr [ebp-4]

    .text:0040129D                 fmul    ds:flt_40711C

    .text:004012A3                 fstp    dword ptr [ebp-4]

    .text:004012A6                 jz      short near ptr loc_4012AA+1

    .text:004012A8                 jnz     short near ptr loc_4012AA+1

    .text:004012AA                 call    near ptr 48CB15h

    .text:004012AF                 xor     ax, 7

    .text:004012B3                 fld     dword ptr [ebp-4]

    .text:004012B6                 fcomp   ds:flt_407118

    .text:004012BC                 push    0

    .text:004012BE                              push    offset aCrackme2017Ctf ;

    .text:004012C3                 fnstsw  ax

    .text:004012C5                 sahf

    .text:004012C6                 jnz     short loc_4012D6

    .text:004012C8                 push    offset aRegistrationSu ;

    .text:004012CD                 jmp     short loc_4012DB

    通过分析调试得出,浮点运算过程为序列号的第三位减去第一位和第二位的商,得到的减法结果再乘以第四位,最后再乘以DS:[0040711C]内存处的值0x41800000(十进制数字16的浮点表示法),以上乘法结果再与DS:[00407118]内存处的值0x43C00000(十进制数字384的浮点表示法)进行比较,如果相等则序列号正确,否则错误。

    浮点运算过程

    用数学公式表示为(s(3)-s(1)/s(2))*s(4)*16=384,即:

                  (s(3)-0.2)* s(4)=24

    推算出:s(3)=5,s(4)=5,即序列号为1555

    输入序列号1555,运行结果为:

    =========

     

    指令功能
    AAA 调整加
    AAD 调整除
    AAM 调整乘
    AAS 调整减
    ADC 进位加
    ADD
    AND
    ARPL 调整优先级
    BOUND 检查数组
    BSF 位右扫描
    BSR 位左扫描
    BSWAP 交换字节
    BT 位测试
    BTC 位测试求反
    BTR 位测试清零
    BTS 位测试置一
    CALL 过程调用
    CBW 转换字节
    CDQ 转换双字
    CLC 进位清零
    CLD 方向清零
    CLI 中断清零
    CLTS 任务清除
    CMC 进位求反
    CMOVA 高于传送
    CMOVB 低于传送
    CMOVE 相等传送
    CMOVG 大于传送
    CMOVL 小于传送
    CMOVNA 不高于传送
    CMOVNB 不低于传送
    CMOVNE 不等传送
    CMOVNG 不大于传送
    CMOVNL 不小于传送
    CMOVNO 不溢出传送
    CMOVNP 非奇偶传送
    CMOVNS 非负传送
    CMOVO 溢出传送
    CMOVP 奇偶传送
    CMOVS 负号传送
    CMP 比较
    CMPSB 比较字节串
    CMPSD 比较双字串
    CMPSW 比较字串
    CMPXCHG 比较交换
    CMPXCHG486 比较交换486
    CMPXCHG8B 比较交换8字节
    CPUID CPU标识
    CWD 转换字
    CWDE 扩展字
    DAA 调整加十
    DAS 调整减十
    DEC 减一
    DIV
    ENTER 建立堆栈帧
    HLT
    IDIV 符号整除
    IMUL 符号乘法
    IN 端口输入
    INC 加一
    INSB 端口输入字节串
    INSD 端口输入双字串
    INSW 端口输入字串
    JA 高于跳转
    JB 低于跳转
    JBE 不高于跳转
    JCXZ 计数一六零跳转
    JE 相等跳转
    JECXZ 计数三二零跳转
    JG 大于跳转
    JL 小于跳转
    JMP 跳转
    JMPE 跳转扩展
    JNB 不低于跳转
    JNE 不等跳转
    JNG 不大于跳转
    JNL 不小于跳转
    JNO 不溢出跳转
    JNP 非奇偶跳转
    JNS 非负跳转
    JO 溢出跳转
    JP 奇偶跳转
    JS 负号跳转
    LAHF 加载标志低八
    LAR 加载访问权限
    LDS 加载数据段
    LEA 加载有效地址
    LEAVE 清除过程堆栈
    LES 加载附加段
    LFS 加载标志段
    LGDT 加载全局描述符
    LGS 加载全局段
    LIDT 加载中断描述符
    LMSW 加载状态字
    LOADALL 加载所有
    LOADALL286 加载所有286
    LOCK
    LODSB 加载源变址字节串
    LODSD 加载源变址双字串
    LODSW 加载源变址字串
    LOOP 计数循环
    LOOPE 相等循环
    LOOPNE 不等循环
    LOOPNZ 非零循环
    LOOPZ 为零循环
    LSL 加载段界限
    LSS 加载堆栈段
    LTR 加载任务
    MONITOR 监视
    MOV 传送
    MOVSB 传送字节串
    MOVSD 传送双字串
    MOVSW 传送字串
    MOVSX 符号传送
    MOVZX 零传送
    MUL
    MWAIT  
    NEG 求补
    NOP
    NOT
    OR
    OUT 端口输出
    OUTSB 端口输出字节串
    OUTSD 端口输出双字串
    OUTSW 端口输出字串
    POP 出栈
    POPA 全部出栈
    POPF 标志出栈
    PUSH 压栈
    PUSHA 全部压栈
    PUSHF 标志压栈
    RCL 进位循环左移
    RCR 进位循环右移
    RDMSR 读专用模式
    RDPMC 读执行监视计数
    RDSHR  
    RDTSC 读时间戳计数
    REP 重复
    REPE 相等重复
    REPNE 不等重复
    RET 过程返回
    RETF 远过程返回
    RETN 近过程返回
    ROL 循环左移
    ROR 循环右移
    RSM 恢复系统管理
    SAHF 恢复标志低八
    SAL 算术左移
    SALC  
    SAR 算术右移
    SBB 借位减
    SCASB 扫描字节串
    SCASD 扫描双字串
    SCASW 扫描字串
    SETA 高于置位
    SETB 低于置位
    SETE 相等置位
    SETG 大于置位
    SETL 小于置位
    SETNA 不高于置位
    SETNB 不低于置位
    SETNE 不等置位
    SETNG 不大于置位
    SETNL 不小于置位
    SETNO 不溢出置位
    SETNP 非奇偶置位
    SETNS 非负置位
    SETO 溢出置位
    SETP 奇偶置位
    SETS 负号置位
    SGDT 保存全局描述符
    SHL 逻辑左移
    SHLD 双精度左移
    SHR 逻辑右移
    SHRD 双精度右移
    SIDT 保存中断描述符
    SLDT 保存局部描述符
    SMI  
    SMINT  
    SMINTOLD  
    SMSW 保存状态字
    STC 进位设置
    STD 方向设置
    STI 中断设置
    STOSB 保存字节串
    STOSD 保存双字串
    STOSW 保存字串
    STR 保存任务
    SUB
    SYSCALL 系统调用
    SYSENTER 系统进入
    SYSEXIT 系统退出
    SYSRET 系统返回
    TEST 数测试
    UD0 未定义指令0
    UD1 未定义指令1
    UD2 未定义指令2
    UMOV  
    VERW 校验写
    WAIT
    WBINVD 回写无效高速缓存
    WRMSR 写专用模式
    WRSHR  
    XADD 交换加
    XBTS  
    XCHG 交换
    XLAT 换码
    XOR 异或
    XSTORE  



    指令功能
    EMMS 媒体空MMX状态
    F2XM1 浮点栈顶绝对值
    FADD 浮点加
    FADDP 浮点加出栈
    FBLD 浮点加载十数
    FBSTP 浮点保存十数出栈
    FCHS 浮点正负求反
    FCLEX 浮点检查错误清除
    FCMOVB 浮点低于传送
    FCMOVBE 浮点不高于传送
    FCMOVE 浮点相等传送
    FCMOVNB 浮点不低于传送
    FCMOVNBE 浮点高于传送
    FCMOVNE 浮点不等传送
    FCMOVNU 浮点有序传送
    FCMOVU 浮点无序传送
    FCOM 浮点比较
    FCOMI 浮点比较加载标志
    FCOMIP 浮点比较加载标志出栈
    FCOMP 浮点比较出栈
    FCOMPP 浮点比较出栈二
    FCOS 浮点余弦
    FDECSTP 浮点栈针减一
    FDISI 浮点检查禁止中断
    FDIV 浮点除
    FDIVP 浮点除出栈
    FDIVR 浮点反除
    FDIVRP 浮点反除出栈
    FENI 浮点检查禁止中断二
    FFREE 浮点释放
    FFREEP 浮点释放出栈
    FIADD 浮点加整数
    FICOM 浮点比较整数
    FICOMP 浮点比较整数出栈
    FIDIV 浮点除整数
    FIDIVR 浮点反除
    FILD 浮点加载整数
    FIMUL 浮点乘整数
    FINCSTP 浮点栈针加一
    FINIT 浮点检查初始化
    FIST 浮点保存整数
    FISTP 浮点保存整数出栈
    FISTTP  
    FISUB 浮点减整数
    FISUBR 浮点反减整数
    FLD 浮点加载数
    FLD1 浮点加载一
    FLDCW 浮点加载控制器
    FLDENV 浮点加载环境
    FLDL2E 浮点加载L2E
    FLDL2T 浮点加载L2T
    FLDLG2 浮点加载LG2
    FLDLN2 浮点加载LN2
    FLDPI 浮点加载PI
    FLDZ 浮点加载零
    FMUL 浮点乘
    FMULP 浮点乘出栈
    FNCLEX 浮点不检查错误清除
    FNDISI 浮点不检查禁止中断
    FNENI 浮点不检查禁止中断二
    FNINIT 浮点不检查初始化
    FNOP 浮点空
    FNSAVE 浮点不检查保存状态
    FNSTCW 浮点不检查保存控制器
    FNSTENV 浮点不检查保存环境
    FNSTSW 浮点不检查保存状态器
    FPATAN 浮点部分反正切
    FPREM 浮点部分余数
    FPREM1 浮点部分余数二
    FPTAN 浮点部分正切
    FRNDINT 浮点舍入求整
    FRSTOR 浮点恢复状态
    FSAVE 浮点检查保存状态
    FSCALE 浮点比例运算
    FSETPM 浮点设置保护
    FSIN 浮点正弦
    FSINCOS 浮点正余弦
    FSQRT 浮点平方根
    FST 浮点保存
    FSTCW 浮点检查保存控制器
    FSTENV 浮点检查保存环境
    FSTP 浮点保存出栈
    FSTSW 浮点检查保存状态器
    FSUB 浮点减
    FSUBP 浮点减出栈
    FSUBR 浮点反减
    FSUBRP 浮点反减出栈
    FTST 浮点比零
    FUCOM 浮点无序比较
    FUCOMI 浮点反比加载标志
    FUCOMIP 浮点反比加载标志出栈
    FUCOMP 浮点无序比较出栈
    FUCOMPP 浮点无序比较出栈二
    FWAIT 浮点等
    FXAM 浮点检查
    FXCH 浮点交换
    FXTRACT 浮点分解
    FYL2X 浮点求L2X
    FYL2XP1 浮点求L2XP1
    MOVED 媒体双字传送
    MOVEQ 媒体四字传送
    PACKSSDW 媒体符号双字压缩
    PACKSSWB 媒体符号字压缩
    PACKUSWB 媒体无符号字压缩
    PADDB 媒体截断字节加
    PADDD 媒体截断双字加
    PADDSB 媒体符号饱和字节加
    PADDSIW  
    PADDSW 媒体符号饱和字加
    PADDUSB 媒体无符号饱和字节加
    PADDUSW 媒体无符号饱和字加
    PADDW 媒体截断字加
    PAND 媒体与
    PANDN 媒体与非
    PAVEB  
    PCMPEQB 媒体字节比等
    PCMPEQD 媒体双字比等
    PCMPEQW 媒体字比等
    PCMPGTB 媒体字节比大
    PCMPGTD 媒体双字比大
    PCMPGTW 媒体字比大
    PDISTIB  
    PMACHRIW  
    PMADDWD  
    PMAGW  
    PMULHRIW  
    PMULHRWC  
    PMULHW  
    PMVGEZB  
    PMVLZB  
    PMVNZB  
    PMVZB  
    POR 媒体或
    PSLLD 媒体双字左移
    PSLLQ 媒体四字左移
    PSLLW 媒体字左移
    PSRAD 媒体双字算术右移
    PSRAW 媒体字算术右移
    PSRLD 媒体双字右移
    PSRLQ 媒体四字右移
    PSRLW 媒体字右移
    PSUBB 媒体截断字节减
    PSUBSB 媒体符号饱和字节减
    PSUBSIW  
    PSUBSW 媒体符号饱和字减
    PSUBUSB 媒体无符号饱和字节减
    PSUBUSW 媒体无符号饱和字减
    PSUBW 媒体截断字减
    PUNPCKHBW 媒体字节高位解压
    PUNPCKHDQ 媒体双字高位解压
    PUNPCKHWD 媒体字高位解压
    PUNPCKLBW 媒体字节低位解压
    PUNPCKLDQ 媒体双字低位解压
    PUNPCKLWD 媒体字低位解压

    ===========
     
  • 相关阅读:
    Gvim快捷键学习
    一步一步学习Vim 全图解释
    经典vim插件功能说明、安装方法和使用方法介绍
    中国数学数字图书馆
    RQNOJ第一题---PID1 / 明明的随机数
    gdb常用命令
    linux c下mysql编程样例
    linux c编程 -- 线程互斥
    linux c多线程编程范例
    数据结构 -- 可重用模块的接口设计模板
  • 原文地址:https://www.cnblogs.com/yue31313/p/7429461.html
Copyright © 2011-2022 走看看