REVERSE-PRACTICE-BUUCTF-20

  • [SCTF2019]creakme
  • [网鼎杯 2020 青龙组]bang
  • [WUSTCTF2020]funnyre
  • Dig the way

[SCTF2019]creakme

exe程序,运行后提示输入ticket,无壳,用ida分析
交叉引用字符串“please input your ticket:”来到sub_402540函数

分析sub_402320函数,在DebugBreak和return之间有一段代码引用

修改EIP从地址0x402412处开始执行,调试可知sub_402450函数是对.SCTF段数据的SMC

回到sub_402540函数,往下走
分析sub_4024A0函数,过掉两个反调试,执行SMC好的.SCTF段的代码,发现是将静态可见的字符串">pvfqYc,4tTc2UxRmlJ,sB{Fh4Ck2:CFOb4ErhtIcoLo"变成了动态可见的字符串"nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo="

回到sub_402540函数,往下走
获取输入input,拷贝input到Dst,sub_4020D0函数对Dst进行AES的CBC模式加密,密文存储在v2,令v4=v2,那段动态可见的字符串赋给v6,最后就是比较v4和v6
sub_4020D0->sub_401690
在sub_401690函数中发现两个字符串"sctfsctfsctfsctf"和"sycloversyclover",由于AES的CBC模式加密需要一个偏移量iv与第0块明文异或,于是可以确定iv=“sctfsctfsctfsctf”,key=“sycloversyclover”,参考:AES五种加密模式(CBC、ECB、CTR、OCF、CFB)


已知key,iv,cipher,写解AES.CBC脚本即可得到flag

from Crypto.Cipher import AES
import base64
key="sycloversyclover"
iv="sctfsctfsctfsctf"
cipher=base64.b64decode("nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=")
aes=AES.new(key,AES.MODE_CBC,iv)
print(aes.decrypt(cipher))
#sctf{Ae3_C8c_I28_pKcs79ad4}

[网鼎杯 2020 青龙组]bang

apk文件,jadx-gui打开什么都没有,SecShell提示是加了壳
果然,这个apk加了梆梆的壳

使用frida脚本脱壳

脱壳后的dex文件再用jadx-gui分析,在com.example.how_debug.MainActivity类中找到flag

[WUSTCTF2020]funnyre

elf文件,运行后没有输入,无壳,ida分析
main函数没有被ida识别成函数,是因为有花指令
jz和jnz指令都会跳转到同一条(下一条)指令,把jz和jnz都nop掉
call后面的地址不存在,是因为在原本正确的指令字节基础上加了多余的字节,把call那条指令按d转成数据后,顺序地一个一个nop掉多余的字节,直到ida能够正确识别出指令
jz指令跳过了从地址0x400621开始的两个字节,也是直接nop掉jz

总共有4处类似这样的花指令,去除完全后,选中main函数的全部红色代码,按p创建函数,F5反汇编
main函数中,验证输入的长度是否为38,且有flag{}包住,对花括号内的32个字符做300多次运算,最后与已知的unk_4025C0比较,验证输入

angr参考:angr学习【一】
脚本参考:buuctf刷题记录25 [WUSTCTF2020]funnyre
调用angr框架写脚本即可得到flag

import angr
import claripyp=angr.Project('./attachment',load_options={"auto_load_libs": False})
f=p.factory
state = f.entry_state(addr=0x400605)#设置state开始运行时的地址
flag = claripy.BVS('flag',8*32)#要求的内容有32个,用BVS转成二进制给flag变量
state.memory.store(0x603055+0x300+5,flag)#因为程序没有输入,所以直接把字符串设置到内存
state.regs.rdx=0x603055+0x300
state.regs.rdi=0x603055+0x300+5#然后设置两个寄存器sm = p.factory.simulation_manager(state)#准备从state开始遍历路径print("ready")sm.explore(find=0x401DAE)#遍历到成功的地址if sm.found:print("sucess")x=sm.found[0].solver.eval(flag,cast_to=bytes)print(x)
else:print('error')
#ready
#sucess
#b'1dc20f6e3d497d15cef47d9a66d6f1af'

Dig the way

exe程序,运行后直接闪退,无壳,ida分析
栈溢出的题目
main函数的主要逻辑为
读取data文件到v7,执行func0,func1和func2函数,返回值分别赋给v9,v10和v11,如果v11为0,则调用get_key函数获得flag。但是对于func2函数,无论传入的参数为何值,其返回值永远为正,v11不可能为0,而对于func1函数,如果传入的参数合适,其返回值可以为0,于是便需要通过func0函数交换v15和v16所存储的函数指针,使得执行func1函数时,其返回值可以赋给v11

int __cdecl main(int argc, const char **argv, const char **envp)
{int result; // eaxint v4; // ebxsize_t v5; // eaxint v6; // ebxchar v7[20]; // [esp+1Ch] [ebp-48h]int v8; // [esp+30h] [ebp-34h]int v9; // [esp+34h] [ebp-30h]int v10; // [esp+38h] [ebp-2Ch]int v11; // [esp+3Ch] [ebp-28h]int v12; // [esp+40h] [ebp-24h]int v13; // [esp+44h] [ebp-20h]signed int (__cdecl *v14)(int, int, int); // [esp+48h] [ebp-1Ch]int (__cdecl *v15)(int, int, int); // [esp+4Ch] [ebp-18h]int (__cdecl *v16)(int, int, int); // [esp+50h] [ebp-14h]int v17; // [esp+54h] [ebp-10h]int v18; // [esp+58h] [ebp-Ch]FILE *v19; // [esp+5Ch] [ebp-8h]__main();v14 = func0;                                  // 交换值v15 = func1;                                  // 含abs的运算,返回值可正可负可零v16 = func2;                                  // 含abs的运算,返回值永正v8 = 0;v9 = 1;v10 = 2;v11 = 3;v12 = 3;v13 = 4;v19 = fopen("data", "rb");                    // 打开data文件流if ( !v19 )return -1;fseek(v19, 0, 2);                             // 指针指到文件流末尾v18 = ftell(v19);                             // 获取文件大小fseek(v19, 0, 0);                             // 指针指回文件开始v17 = ftell(v19);if ( v17 ){puts("something wrong");result = 0;}else{for ( i = 0; i < v18; ++i ){v4 = i;v7[v4] = fgetc(v19);                      // data文件的字节读到v7// 由于v7只是个20字节大小的数组,如果data文件中的字节数大于20,则会把v8~v13的值覆盖掉,即栈溢出}v5 = strlen(v7);if ( v5 <= v18 ){v18 = v11;                                // v18=v11,且v18在获取flag的函数get_key中用到i = 0;v17 = v13;while ( i <= 2 ){v6 = i + 1;*(&v8 + v6) = (*(&v14 + i))((int)&v8, v12, v13);// 执行func0,func1和func2,返回值分别赋给v9,v10,v11v12 = ++i;                              // v12和v13用i赋值v13 = i + 1;}if ( v11 ){result = -1;}else                                      // v11为0时,执行get_key获得flag{get_key(v18, v17);system("PAUSE");result = 0;}}else{result = -1;}}return result;
}

由于程序读取data文件是从头到尾全部读取,而v7只有20个字节大小,如果data文件的字节数大于20,多出来的字节就会将v8,v9,v10等等这些变量覆盖
v12和v13被程序赋值为3和4,进入func0函数后并不能达到交换v15和v16的目的,因为此时func0函数中参与运算的变量为v11和v12,而不是v15和v16。于是便利用程序读data文件有可能覆盖v12和v13的漏洞,将v12和v13覆盖为7和8
v7有20个字节,v8~v11是4个int,也就是4x4=16个字节,于是data文件需要从第36个字节开始,将v12和v13覆盖为7和8,data为

发现exe程序还是运行后闪退,调试发现func1函数的返回值v11还是为正
仔细看调用func0~func2这部分代码,在v12和v13分别为7和8作为参数传入func0函数交换v15和v16后,v15执行func2函数,v16执行func1函数,而在循环中v12和v13由i赋值,当执行v16(func1)函数时,v12和v13的值分别为2和3

也就是说,func1函数执行时,实际上是abs(v10+v11)-abs(v11)-abs(v10)+2,v10等于2,要使返回的值为0,则需v11为-1,于是同样利用程序data读文件的漏洞将v11覆盖为-1,data为

再次运行exe程序,得到flag

REVERSE-PRACTICE-BUUCTF-20相关推荐

  1. 金海佳学C++primer 练习9.20

    将list中的元素按奇偶分到两个deque中 Practice 9.20 #include <iostream> #include <string> #include < ...

  2. 转载:C++ list 类学习笔记

    声明:本文转自http://blog.csdn.net/whz_zb/article/details/6831817 双向循环链表list list是双向循环链表,,每一个元素都知道前面一个元素和后面 ...

  3. 如何在Python中反转列表?

    如何在Python中执行以下操作? array = [0, 10, 20, 40] for (i = array.length() - 1; i >= 0; i--) 我需要一个数组的元素,但是 ...

  4. Leetcode:The Skyline Problem

    题目大意:太复杂了,不太想翻译.对于一丛相互交错的方形建筑,可以由一个二维数组表示各自的轮廓.求从远处观望时看到的天际线.所谓的天际线就是某一段水平区域上的等高线,其下方或者是建筑,或者是地面.求从左 ...

  5. python密码学编程pdf-Python密码学编程 PDF 下载

    相关截图: 资料简介: Python是一种高级程序设计语言,因其简洁.易读及可扩展性日渐成为程序设计领域备受推崇的语言.同时,Python语言在算法领域也得到了很好的应用.本书通过理论和实例相结合的方 ...

  6. 微软算法100题26 左旋转字符串

    26.左旋转字符串 题目: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部. 如把字符串abcdef 左旋转2 位得到字符串cdefab.请实现字符串左旋转的函数. 要求时间对长度 ...

  7. BZOJ1566 [NOI2009]管道取珠

    这是一道思维复杂度很高的DP题 看题目,为什么是取两次序列一样呢?YY一下,其实等价于两个人一起取,最后序列一样. 然后就水了: 令f[i, j, k]表示取到第i个珠子,第一个人在1号管道取了j个珠 ...

  8. STL中list的使用(理论)

    STL中的list就是一双向链表,可高效地进行插入删除元素.现总结一下它的操作. 文中所用到两个list对象c1,c2分别有元素c1(10,20,30) c2(40,50,60).还有一个list&l ...

  9. python 属性描述符_Python属性描述符(二)

    Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性,但如果实例未曾定义过该属性,就会获取类属性,而为实例的属性赋值时,通常会在实例中创建属性,而不会影响到类本身.这 ...

  10. 有效单元测试之可读性

    断言 断言的基本原理和意图隐藏在无意义的单词和数字背后,难以理解,难以验证断言的正确性. Bad eg. @Test public void outputHasLineNumbers() {Strin ...

最新文章

  1. 网络工程与机房等精华指引贴
  2. AI大牛纷纷离职!2021大厂AI Lab现状盘点,网友:名存实亡
  3. Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析...
  4. 一个mui+ajax+php的demo
  5. oralce创建用户
  6. java类加载器 架构 设计_类加载器(DexClassLoader)与插件化(动态加载)
  7. 宝宝的成长脚印6/15
  8. vscode代码运行时间工具_10款实用的VSCode插件提升你的编辑体验 | 第98期
  9. PCA对特征点描述子降维
  10. 【C++】局部变量、全局变量、静态变量与动态对象的性质
  11. Java基础笔记(三)
  12. MiPony– 杀手级免费网盘下载工具 可挂机下载支持YunFile
  13. 在虚拟机里配置mysql环境
  14. Attacking Black-box Recommendations viaCopying Cross-domain User Profiles
  15. 洛谷 P1719 最大加权矩形 动态规划
  16. 【为你剖析笔记本的内部结构】
  17. apple iMac一体机 装双系统 实战! (Apple +Win 7 64bit)Good
  18. 【农业科研进展】小麦白粉病与植物叶部病害监测识别
  19. 何金龙 mysql_办innodb
  20. 计算机组成原理TEC-8,南信大 计算机组成原理实验TEC-8实验指导书.pdf

热门文章

  1. 如何配置一个最基本的web富文本编辑器?--之wangEditor(验证成功)
  2. maven生成javadoc【原创】
  3. 磁盘 I/O 性能监控指标和调优方法
  4. eveningplan
  5. [Leetcode][第题][JAVA][两个数组的交集 II1][双指针][HashMap]
  6. codeUp 2031 To fill or not to fill 复杂贪心
  7. Linux网络设备描述符,Linux
  8. ubuntu安装提醒写入失败 没有启动项_手把手教你如何安装windo10+Ubuntu18.10双系统...
  9. rs232串口驱动_电脑主板RS232串口硬件设计
  10. Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)(A - D)