看雪 2016 CTF 第八题 点评和解析

回复 星标
更多

看雪 2016 CTF 第八题 点评和解析

看雪版主&评委

netwind点评

此题是一道简单的算法题,根据字符串提示信息以及下断关键API可以定位到注册算法的位置,算法是一个数学关系式,求解便可以得到答案

出题者简介:

无名侠,目前在研究Android安全,也参加信息学奥林匹克竞赛。

下面选择了一位分析者破解pj的详细分析:

1. 发现cm 64位程序,先拖进ida 看看流程,发现很清晰。

IDA查找字符串找到可疑地方

508547

两处字符串 一处是恭喜注册成功,一处是注册提示

进去看看,找到调用的地方,流程图有点多,我们菜鸟必备技能,F5

看到可疑算法部分

508547

508547

那问题来了,如何找到关键地方呢?

答:就是动态分析,为啥要动态分析呢?因为参数原因 你要看参数是什么。

要分析,你要用调试工具呀。

如何寻找x64调试工具呢?

答:找了好几个,例如:

a. windbg 没界面感觉不好用。

b. Visual DuxDebugger  这个感觉不太友好,好多功能都没有。

c. MDebug_x64 这个感觉还行。

经介绍各位导师介绍x64dbg ,拿到这个感觉,这不是od吗?

虽然和od 想比有些功能很鸡肋,但是我认为已经是众多x64调试工具里面比较好的。纯属个人观点。这段可以跳过 ,不bb了。感谢开源 感谢这个作者.

2. 有了工具 和算法关键地方 还怕什么,直接开整起来.

怎么找到ida 看到的一些可疑的地方呢?

一开始想用字节搜素定位过去,测试没成功。

那就是基址函数头偏移大法.

Ida 函数头偏移是14B0

508547

X64dbg 找到基址 Alt+M或者视图——内存分布 基地址:000000013F4C0000

508547

Ida函数头偏移+程序基址=000000013F4C0000+14B0

跳转这个地方,对比ida 查找正确

508547

2.1先找到爆破点,再找算法。

单步走下去。注意跳转。下面是爆破点

508547

跳过去就会成功 否则错误。

2.2 找到爆破地方向上分析

找到谁影响ecx eax

输入假码 123456

A678是另外一个算法 和输入相关。我们暂且不讨论这个

经过分析上面算法发现

[000000013F695CC0+c*4] 这个是固定的数值134, 已知的量

A678*2+[000000013F695CC0+c*4]=3*A678

看这个像什么 这个不是小学的解一元一次方程吗

A678设为x

2x+134=3x 解 x=134

(注意134为 16进制)

2.3 查找输入相关的算法

这个算法只要查找A678怎么来的

Ida 字符串嫌疑法  假码处理 这个就是输入处理算法

508547

继续基址函数头偏移,定位到关键算法地方 IDA F5  动态调试也可以分析

就是这个地方

508547

这个代码vc可以直接编译, 修改下 就可以

这个算法结果存放到v1

v1结果为 134

只有(signed int)(v1 * v1) % v3 == v2才终止循环

通过算法分析

v3=10^v6

V6是长度

测试 答案不唯一 4864 94864

508547

508547

具体源码如下

##include <stdio.h>

#include <iostream.h>

signed int jisuan( int a1);

int main()

{

int result=jisuan(123456);

int nxx3=(0x134*0x134)%1000;

int nxx4=(0x134*0x134)%10000;

int nxx5=(0x134*0x134)%100000;

int nxx6=(0x134*0x134)%1000000;

int nxx7=(0x134*0x134)%10000000;

int nxx8=(0x134*0x134)%100000000;

//4864 94864 答案不唯一 nxx 就是输入的注册码

return result;

}

signed int jisuan( int a1)

{

unsigned int v1; // er9@1

signed int v2; // er11@1

signed int v3; // er8@1

signed int v4; // er10@1

__int64 v6; // rax@8

v1 = 0;

v2 = a1;

v3 = 1;

v4 = 0;

if ( a1 == 874 || a1 == 987654321 )

return 0xFFFFFFFFi64;

if ( a1 )

{

do

{

++v4;

a1 /= 10;

}

while ( a1 );

if ( v4 < 1 )

goto LABEL_10;

}

else

{

v4 = 1;

}

v6 = (unsigned int)v4;

//v6 长度

do

{

v3 *= 10;

--v6;

}

while ( v6 );

// v3=10^v6

do

LABEL_10:

++v1;

while ( (signed int)(v1 * v1) % v3 != v2 );

return v1;

}

508547

508547

看雪安全 · 看雪众测

持续关注安全16年,专业为您服务!

快,关注这个公众号,一起涨姿势~

508547

此帖已被锁定,无法回复
新窗口打开 关闭