目录

一.主函数逻辑

二.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;    //-号修改为+号elseinput[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{d07abccf8a410creturn 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栈指针的修复以及函数调用,栈平衡后续会写一篇文章专门讲解

Buuctf [网鼎杯 2020 青龙组]jocker 题解相关推荐

  1. re -25 buuctf [网鼎杯 2020 青龙组]jocker

    [网鼎杯 2020 青龙组]jocker 前话:ida7.6设置栏内没有general,可以通过ctrl+shift+p打开命令面板,搜索option打开设置选项,于Disassembly设置堆栈显示 ...

  2. [BUUCTF][网鼎杯 2020 青龙组]jocker 分析与记录

    无壳,IDA打开可以直接进入main函数: 第12行调用VirtualProtect函数更改了offset encrypt处的访问保护权限 BOOL VirtualProtect(LPVOID lpA ...

  3. BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker

    BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker 先看下文件信息,没有加壳,32位程序 运行一下,又是一道字符串比较的题目 用IDA32位打开,分析一下 // positive ...

  4. [网鼎杯 2020 青龙组]jocker

    [网鼎杯 2020 青龙组]jocker SMC(self-Modifying Code): 自修改代码,程序在执行某段代码的过程中会对程序的代码进行修改,只有在修改后的代码才是可汇编,可执行的.在程 ...

  5. Buuctf[网鼎杯 2020 青龙组]AreUSerialz

    [网鼎杯 2020 青龙组]AreUSerialz 打开题目仔细阅读源码 <?phpinclude("flag.php"); highlight_file(__FILE__) ...

  6. [BUUCTF]Reverse——[网鼎杯 2020 青龙组]jocker

    网上大部分是动调,我尝试IDC解一下, 无壳,32位,放入IDApro,查看main函数 查看wrong和str函数,借出假的flag a=[0x66,0x6B,0x63,0x64,0x7F,0x61 ...

  7. buuctf刷题记录21 [网鼎杯 2020 青龙组]jocker

    今天挑战一下,结果最后还是看了别人的wp才写出来的 无壳,ida查看发现不能f5,原因堆栈不平衡 进行栈指针修改 修改出错的地方的栈指针偏移,快捷键alt+k,值改为0 然后就能f5了, 逻辑也不难, ...

  8. BUUCTF·[网鼎杯 2020 青龙组]boom·WP

    BUUCTF在线评测 (buuoj.cn) 附件 是一个可运行的文件 回车出现: 分析 猜测是C编写的,拉到编译器,发现提示是二进制文件 那就用010Editor打开 查找了一下flag,这不就是跟附 ...

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

    首先我们查看一下信息,32位程序,无壳: 然后用IDA打开,提示// positive sp value has been detected, the output may be wrong! 出现了 ...

最新文章

  1. java robot 对象_用Java Robot对象实现服务器屏幕远程监视
  2. 《面向对象程序设计课程学习进度条》
  3. 首次构建android studio gradle 下载缓慢的问题
  4. 用户设置及用户默认设置
  5. qt 等待线程结束_c – 停止Qt线程:调用exit()或quit()不会停止线程执行
  6. 微软开始取消 Windows 10 对 32 位系统的支持
  7. MATLAB 检验矩阵中是否有某些元素 对元素统计
  8. 在测试中发现错误,不要着急去改,静下心来,想一想错误的关联性( 错误展开确认 )。
  9. 计算机组织原理答案白中英,计算机组成原理答案-白中英
  10. 大漠插件7.2137
  11. Linux的拓扑结构,linux底下的makefile框架拓扑结构分析
  12. U3D教程多摄像机协同运行
  13. 能净化空气的PC电源,配置也很不错,艾湃电竞AP-550Ti体验
  14. 微信小程序中显示换行、空格
  15. H5网页使用支付宝授权登录获取用户信息详解
  16. Android根据图片路径获取图片名字
  17. 提升树(Boosting tree)算法总结
  18. (AAAI-2019)用于行人重识别的水平金字塔匹配
  19. 三面(技术+HR面试)网易,分享我的面试经验!(已拿offer)
  20. FastAPI上传POST嵌套JSON对象及List列表BaseModel,python

热门文章

  1. python爬html网站
  2. 小谈一下农业银行的信用卡网上支付使用感受
  3. 防火墙阻断扫描设备_记一次故障排查
  4. 【深入理解计算机网络】入门计算机网络基础视频课程(下)-王达-专题视频课程...
  5. 路由器固件模拟环境搭建(超详细)
  6. 即时通讯,IM,聊天交友,同城交友,同城约会APP源码
  7. 微信公众服务号怎么一天发一条图文消息?
  8. 什么水果含维生素B最多
  9. Linux文件属主显示数字
  10. buu [QCTF2018]Xman-RSA 1