Buuctf [网鼎杯 2020 青龙组]jocker 题解

目录

一.主函数逻辑

二.wrong函数和omg函数--假flag

1.wrong函数

2.omg函数

3.假flag

 三.encrypt和finally函数--真flag

1.打开sp指针偏移显示

2.修复sp指针偏移值

3.动态调试得到正确的encrypt和finally函数

(1)得到正确的encrypt函数

(2)得到正确的finally函数

四.解题脚本

1.flag前一段

2.flag第二段

五.参考文章


一.主函数逻辑

 

1.提示:// positive sp value has been detected, the output may be wrong!,出现了堆栈不平衡的情况

2.VirtualProtect函数的作用是取消encrypt函数所在区域的读写保护,为下方给函数脱壳做准备

3.首先输入一个字符串input,判断长度是否为24,然后复制到str中;

4.wrong函数对input串加密,加密后由omg函数进行判断是否满足条件,但是根据这两条函数得到的flag是假的,也就图一乐

5.真正的flag要根据encrypt和finally函数以及str串(原始的input)来求得

二.wrong函数和omg函数--假flag

1.wrong函数

很普通的一个加密

2.omg函数

很普通的一个判断

其中arr数组的内容可以通过4030c0区域提取得到,选中数据右键->convert->以dword形式输出

3.假flag

根据这两个函数可以写出解题脚本,但是输出的是假flag: flag{fak3_alw35_sp_me!!}

不过这个假flag就是我们要输入的字符串,下面还有作用

#include <stdio.h>
int main()
{
    unsigned int input[25] = {
    0x00000066, 0x0000006B, 0x00000063, 0x00000064, 0x0000007F, 0x00000061, 0x00000067, 0x00000064,
    0x0000003B, 0x00000056, 0x0000006B, 0x00000061, 0x0000007B, 0x00000026, 0x0000003B, 0x00000050,
    0x00000063, 0x0000005F, 0x0000004D, 0x0000005A, 0x00000071, 0x0000000C, 0x00000037, 0x00000066,0
    };
    int chr;
    for (int i = 0; i <= 23; ++i)
    {
        if ((i & 1) != 0)
            input[i] += i;    //-号修改为+号
        else
            input[i] ^= i;
        printf("%c", input[i]);
    }
    //flag{fak3_alw35_sp_me!!}
    //假密码
    return 0;
}

 

 三.encrypt和finally函数--真flag

直接点击encrypt或finally函数会提示错误,并显示汇编代码,如果是框图形式可以按空格键转换一下

查看汇编代码不难发现有sp栈指针错误

1.打开sp指针偏移显示

在options>general>disassembly中,勾选上stackpointer

此时可以发现在地址和十六进制指令中间多了一列蓝色数字,这行数字代表的就是本条指令执行后sp指针的偏移值会是多少(应该是根据bp来计算的)

2.修复sp指针偏移值

我们回到主函数反汇编窗口,按tab键转换为汇编窗口,往下翻找到call 指令部分

选中call __Z7encryptPc这行指令,按alt+k,将新旧sp偏移值改成0;

这样操作后可以发现偏移值正常了,然后对下方的call __Z7finallyPc做相同操作

按f5也可以发现主函数没有了sp指针错误的提示

不过仍然进不去encrypt函数,finally函数也是很丑陋的一大段,这是由于encrypt函数还没有被去壳

3.动态调试得到正确的encrypt和finally函数

回到main函数,在if ( encrypt(Str) )这里下断点,开始动态调试,输入上面的假flag即可通过omg判断

(1)得到正确的encrypt函数

在main中点击encrypt函数,仍然不能反汇编,我们找到encrypt函数定义处对应的汇编代码

从定义头一直到endp,还有下方这一块区域,全部选中之后按u(undefined)取消定义,再在定义头按p即可识别为函数

取消定义重新识别后按f5成功得到encrypt函数

在这里可以dump下来403040和Buffer串的内容:

unsigned int dword_403040[19] = {
    0x0000000E, 0x0000000D, 0x00000009, 0x00000006, 0x00000013, 0x00000005, 0x00000058, 0x00000056, 
    0x0000003E, 0x00000006, 0x0000000C, 0x0000003C, 0x0000001F, 0x00000057, 0x00000014, 0x0000006B, 
    0x00000057, 0x00000059, 0x0000000D
};

unsigned char Buffer[]="hahahaha_do_you_find_me?";

值得一提的是动态调试结束后encrypt函数又会识别错误,这是因为每次运行程序会执行脱壳代码,而回到静态调试时会回到脱壳前的状态,所以导致识别错误

(2)得到正确的finally函数

在上一步的基础上,继续往下翻找到__Z7finallyPc,也是相同处理方法(包括下方一大段数据)

finally函数重新识别后在静态分析中也有效

得到反汇编代码:

四.解题脚本

1.flag前一段

根据encrypt函数的内容可以写出这个脚本,得到flag{d07abccf8a410c

显然还缺少了一段,这段需要分析finally函数

#include <stdio.h>
int main()
{
    unsigned int dword_403040[19] = {
    0x0000000E, 0x0000000D, 0x00000009, 0x00000006, 0x00000013, 0x00000005, 0x00000058, 0x00000056,
    0x0000003E, 0x00000006, 0x0000000C, 0x0000003C, 0x0000001F, 0x00000057, 0x00000014, 0x0000006B,
    0x00000057, 0x00000059, 0x0000000D
    };
    unsigned char Buffer[25] = "hahahaha_do_you_find_me?";
    unsigned char flag[25] = { 0 };
    for (int i = 0; i < 19; i++)
    {
        flag[i] = dword_403040[i] ^ Buffer[i];
        printf("%c", flag[i]);
    }
    //flag{d07abccf8a410c
    return 0;
}

2.flag第二段

这个非常迷惑,分析上面得到的反汇编代码无处下手,因为判断条件中有个随机数,看了其他大佬的wp

"%tp&:"这个字符串是最后一段,flag的最后一个字符是'}'根据题目描述的异或操作,可能是这段字符使用同一个值异或,所以只要由':'^n='}'得到这个用于异或的值即可求出其他字符

char n = ':' ^ '}', arr[6] = "%tp&:";
    for (int i = 0; i < 5; i++)
    {
        arr[i] ^= n;
        printf("%c", arr[i]);
    }
    //b37a}

所以flag{d07abccf8a410cb37a}

五.参考文章

1.[网鼎杯 2020 青龙组]jocker(详解)

2.IDA出现"sp-analysis failed"和F5(反编译)失败

3.IDA为什么产生 sp-analysis failed 错误?

4.C/C++ 函数的调用约定详解

5.【汇编 C】C语言常用的三种函数调用约定:__cdecl、__stdcall、__fastcall

6._stdcall与_cdecl区别

对于sp栈指针的修复以及函数调用,栈平衡后续会写一篇文章专门讲解

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这个错误是在运行命令"./configure"时出现的。错误提示是"configure: error: /bin/sh ./config.sub /d/project/nc_file_format/hdf5-1.10.6/install/lib failed"。根据引用,这个错误可能是由于找不到或无法执行config.sub文件导致的。 根据引用中的解决方法,你可以尝试用系统中的config.sub文件替换掉当前目录下的config.sub文件。你可以使用以下命令进行替换: mv /home/joy/config/config.sub /home/joy/config/config.sub.bak cp /usr/share/libtool/build-aux/config.sub /home/joy/config/config.sub mv /home/joy/config/config.guess /home/joy/config/config.guess.bak cp /usr/share/libtool/build-aux/config.guess /home/joy/config/config.guess 这样做可以确保你使用的是系统中的config.sub文件,从而解决配置错误。 此外,你也可以使用引用中的命令查找系统中所有的config.sub文件,与你当前目录下的进行比较,以确定是否存在其他引起错误的config.sub文件。你可以使用以下命令进行查找: find / -name config.sub 这会在系统中查找所有名为config.sub的文件,并输出它们的路径。你可以将这些路径与你当前目录下的config.sub进行比较,以找到可能引起错误的文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [configure: error: cannot run /bin/bash config/config.sub](https://blog.csdn.net/Jocker_xie/article/details/89332120)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OrientalGlass

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值