看雪论坛 破解exe 看雪CTF2017第一题分析-『CrackMe』-看雪安全论坛
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha
逆向 黑客 破解 学习 论坛
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 i in range ( 126 ): for j 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 | 媒体字低位解压 |