本期题目
https://github.com/Kinotern/CTFLifefromZero/tree/main/01
主要是带着你过一次,看着学学然后记住一些基本的操作
现有如下程序及编译附带产物(面向新手展示IDA功能用)

测试exe看看有啥线索
打开exe显示

随便输入看看显示错误按任意键退出
====================================
IDA Beginner CrackMe v1
====================================
Password: 111
Wrong password. Try again.
Press Enter to exit...
有Password字符串,记住
IDA相关
打开IDA
点击New

选择exe打开

点击OK

点击yes

回顾记忆
打开了对吧,不要慌别慌别放弃
你面对这一对不知道怎么用很正常
还记得我们之前找到的字符串Password吗?
知识点1
Shift + F12 查找字符串

按下后显示这个字符串界面

随便点击一行的string一下,这里看图
然后直接在键盘输入pass
那么他自动会带我们去找到它,然后双击Srting列的Password

查找引用
点击后会跳转到asm处
这一行main+18↑o双击它
找到是什么引用了他

第二处引用分析
那么我们耐心地仔细看看分析看图
Password,然后跳转到check_password

往下继续分析调用
check之后正确,提示成功Correct!所以需要追踪他到底是如何检查的
我们肯定先需要长度,然后知道格式,然后再一层层解密下去
双击check_password
你看有几处调用
有check_length检查长度,check_prefix检查前缀,check_middle中段检查,check_suffix尾缀检查
需要有一定英文词汇量,实在不会就查一下嘛

知识点2
按下F5反汇编为.c
先双击check_length,跳转到
重点是
return j_strlen(Str: input) == 13;
返回 Str: input(即字符输入长度)等于13 的判断结果
即
if (strlen(input) == 13) {
return true;
} else {
return false;
}
知识点3
返回上一处跳转点击左上角箭头
反之亦然

分析检查check_prefix前缀

这里有四个input=数字
说明前缀有四位东西
知识点4
反汇编上方的灰色字是什么
const char *input,char * 通常表示字符串
反编译出来的东西意味着
从字符串里取出单个 char 字符
并且数字范围像可打印字符
知识点5
可打印 ASCII 范围:
32 到 126
我们需要翻表吗?暂时没必要
选中这个数字

按下键盘R就可以了

说明第一位是I,第二位是D,第三位是A,第四位是-
说明密码是
IDA-XXXXXXXXX
继续分析检查中间的函数
双击它

这里需要小小的计算
{
if ( input[6] + input[5] + input[4] != 249 )
return false;
if ( input[4] != 78 )
return false;
if ( input[5] == input[4] + 23 )
return input[6] == 70;
return false;
}
注意之前分析前缀的I是 input对吧
也就是input[0],他是从0开始的顺序
所以出现的input[4]是第五位,剩余同理
它检查的是第 5、6、7 个字符
第一句:
input[6] + input[5] + input[4] != 249
说人话就是
如果 input[4]、input[5]、input[6] 三个字符的 ASCII 总和不等于 249,就失败。
先放着,它是一个总校验
第二句更直接:
if ( input[4] != 78 )
return false;
如果 input[4] 不是 78,就失败。
78对应的ASCII 码是N
所以第五位是N
所以密码为
IDA-NXXXXXXXX

第三句
if ( input[5] == input[4] + 23 )
即
if ( input[5] == 78 + 23 == 101)
这里就得自己去查一下表了
所以第六位是101对应ASCII的e
密码目前为
IDA-NeXXXXXXX
第四句也是直接告诉你了
return input[6] == 70;
return input[6] == 'F';
第七位是F
密码目前为
IDA-NeFXXXXXX
回到第一句我们检验一下
input[6] + input[5] + input[4] != 249
70+101+78=249
核对一下没问题正确!
接下来分析check_suffix,检查尾缀
_BOOL8 __fastcall check_suffix(const char *input)
{
char expected[8]; // [rsp+30h] [rbp-18h] BYREF
strcpy(expected, "LOVE!");
return input[7] == 45 && j_strcmp(Str1: input + 8, Str2: expected) == 0;
}
这段函数先创建了一个本地字符串变量 expected如何看出来的呢?
知识点6
变量声明格式
char expected[8];
创建一个 char 类型的数组,名字叫 expected,大小是 8 个字节
在 C 语言里,char 数组 经常用来存字符串
strcpy(expected, "LOVE!");
把 "LOVE!" 复制到 expected 里面。
strcpy意思:
strcpy = string copy = 复制字符串
它的基本形式是:
strcpy(目标, 来源);
下面又有
return input[7] == 45 && j_strcmp(Str1: input + 8, Str2: expected) == 0;
即return input[7] == '-'
第八位是-
IDA-NeF-XXXXX
显然剩下的五位就是LOVE!
规范一下就是
check_suffix 先把 expected 设置成 "LOVE!",
然后要求 input[7] 即第八位 是 '-',
并且要求从 input[8] 即第九位 开始的字符串等于 "LOVE!"。
因此最后一段是 "-LOVE!"。
至此密码就是
IDA-NeF-LOVE!
输入验证

知识点总结
Shift + F12 查找字符串
按下F5反汇编为.c
返回上一处跳转点击左上角箭头
反汇编上方的灰色字是什么
const char *input,char * 通常表示字符串
反编译出来的东西意味着
从字符串里取出单个 char 字符
并且数字范围像可打印字符
可打印 ASCII 范围:
32 到 126
变量声明格式
示例
char expected[字节大小];
创建一个 char 类型的数组,名字叫 expected,大小是 8 个字节



2 条回复