REVERSE-PRACTICE-BUUCTF-19

REVERSE-PRACTICE-BUUCTF-19

    • [RoarCTF2019]polyre
    • [安洵杯 2019]game
    • [SCTF2019]Strange apk
    • [CFI-CTF 2018]IntroToPE

[RoarCTF2019]polyre

elf文件,无壳,用ida分析
main函数的结构,多重循环,是控制流平坦化,参考:利用符号执行去除控制流平坦化
polyre-main
装好angr,使用脚本deflat.py去除控制流平坦化,脚本取自:deflat
polyre-deflat
polyre-deflat
将去除控制流平坦化的文件attachment_recovered拖入ida中分析
main函数还是不好分析,有很多while和do while循环,实际上是虚假控制流,使用脚本去除虚假控制流,在ida的Script command执行

def patch_nop(start,end):for i in range(start,end):PatchByte(i, 0x90)def next_instr(addr):return addr+ItemSize(addr)st = 0x0000000000401117
end = 0x0000000000402144addr = st
while(addr<end):next = next_instr(addr)if "ds:dword_603054" in GetDisasm(addr):while(True):addr = nextnext = next_instr(addr)if "jnz" in GetDisasm(addr):dest = GetOperandValue(addr, 0)PatchByte(addr, 0xe9)PatchByte(addr+5, 0x90) offset = dest - (addr + 5)PatchDword(addr + 1, offset)print("patch bcf: 0x%x"%addr)addr = nextbreakelse:addr = next

去除虚假控制流之后的main函数
主要逻辑为
输入的字符每8个字节为1组,组成1个64位的signed int v4,对v4进行64次循环运算,如果v4为非负,则v4乘以2,相当于左移1位,最高位的0移出,最低位补零,v4必为偶数(如果左移一位后最高位为1,则v4变成了负数值),如果v4为负,则先左移1位,再与0xB0004B7679FA26B3异或,左移一位时,最高位的1被移出了(写逆运算脚本时需要加回来最高位的1),最低位补零,由于3的二进制为0011,异或后v4必为奇数

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{signed __int64 v4; // [rsp+1E0h] [rbp-110h]signed int j; // [rsp+1E8h] [rbp-108h]signed int i; // [rsp+1ECh] [rbp-104h]signed int k; // [rsp+1ECh] [rbp-104h]char s1[48]; // [rsp+1F0h] [rbp-100h]char input[60]; // [rsp+220h] [rbp-D0h]unsigned int v10; // [rsp+25Ch] [rbp-94h]char *v11; // [rsp+260h] [rbp-90h]int v12; // [rsp+26Ch] [rbp-84h]bool v13; // [rsp+272h] [rbp-7Eh]unsigned __int8 v14; // [rsp+273h] [rbp-7Dh]int v15; // [rsp+274h] [rbp-7Ch]char *v16; // [rsp+278h] [rbp-78h]int v17; // [rsp+284h] [rbp-6Ch]int v18; // [rsp+288h] [rbp-68h]bool v19; // [rsp+28Fh] [rbp-61h]char *v20; // [rsp+290h] [rbp-60h]int v21; // [rsp+298h] [rbp-58h]bool v22; // [rsp+29Fh] [rbp-51h]__int64 v23; // [rsp+2A0h] [rbp-50h]bool v24; // [rsp+2AFh] [rbp-41h]__int64 v25; // [rsp+2B0h] [rbp-40h]__int64 v26; // [rsp+2B8h] [rbp-38h]__int64 v27; // [rsp+2C0h] [rbp-30h]__int64 v28; // [rsp+2C8h] [rbp-28h]int v29; // [rsp+2D0h] [rbp-20h]int v30; // [rsp+2D4h] [rbp-1Ch]char *v31; // [rsp+2D8h] [rbp-18h]int v32; // [rsp+2E0h] [rbp-10h]int v33; // [rsp+2E4h] [rbp-Ch]bool v34; // [rsp+2EBh] [rbp-5h]v10 = 0;memset(input, 0, 0x30uLL);memset(s1, 0, 0x30uLL);printf("Input:", 0LL);v11 = input;__isoc99_scanf("%s", input);for ( i = 0; ; ++i ){v12 = i;v13 = i < 64;if ( i >= 64 )break;v14 = input[i];v15 = v14;if ( v14 == '\n' )                          // 换行符'\n'改成字符串结束符'\0'{v16 = &input[i];*v16 = 0;break;}v17 = i + 1;}for ( j = 0; ; ++j ){v18 = j;v19 = j < 6;if ( j >= 6 )                               // 循环6次break;v20 = input;v4 = *(_QWORD *)&input[8 * j];              // 输入的每8个字节一组,组成1个64位的v4,小端序for ( k = 0; ; ++k ){v21 = k;v22 = k < 64;if ( k >= 64 )                            // 循环64次break;v23 = v4;v24 = v4 < 0;if ( v4 >= 0 )                            // 如果v4非负,v4*=2,相当于左移一位,结果必为偶数,如果左移一位后最高位为1,则v4变成了负数{v27 = v4;v28 = 2 * v4;v4 *= 2LL;}else                                      // 如果v4为负,v4乘2后再异或0xB0004B7679FA26B3,相当于先左移一位再异或,结果必为奇数,注意这时最高位的1被移出了{v25 = 2 * v4;v26 = 2 * v4;v4 = 2 * v4 ^ 0xB0004B7679FA26B3LL;}v29 = k;}v30 = 8 * j;v31 = &s1[8 * j];                           // 每组完成64次循环后的值赋给s1*(_QWORD *)v31 = v4;v32 = j + 1;}v33 = memcmp(s1, &unk_402170, 48uLL);         // s1和已知值比较,小端序v34 = v33 != 0;if ( v33 != 0 )puts("Wrong!");elseputs("Correct!");return v10;
}

写逆运算脚本即可得到flag

#coding:utf-8
arr=[0x96, 0x62, 0x53, 0x43, 0x6D, 0xF2, 0x8F, 0xBC, 0x16, 0xEE,0x30, 0x05, 0x78, 0x00, 0x01, 0x52, 0xEC, 0x08, 0x5F, 0x93,0xEA, 0xB5, 0xC0, 0x4D, 0x50, 0xF4, 0x53, 0xD8, 0xAF, 0x90,0x2B, 0x34, 0x81, 0x36, 0x2C, 0xAA, 0xBC, 0x0E, 0x25, 0x8B,0xE4, 0x8A, 0xC6, 0xA2, 0x81, 0x9F, 0x75, 0x55]
enc=[]
for i in range(6):#以小端序的方式读值tmp='0x'for j in range(7,-1,-1):tmp+=hex(arr[i*8+j]).replace('0x','').zfill(2)enc.append(tmp)
flag_data=[]
for i in range(len(enc)):tmp=int(enc[i],16)for j in range(64):#循环64次sign=tmp&1      #判断当前v4的符号 &1后为1即为奇数 为0即为偶数if sign:        #奇数要异或回去tmp^=0xB0004B7679FA26B3tmp//=2          #无论正负都要右移一位回去if sign:        #奇数右移一位后还要补回左移一位时移出的1tmp|=0x8000000000000000flag_data.append(hex(tmp).replace('0x','').replace('L',''))
flag_str=""
for i in range(6):#由于存储方式是小端序 所以需要从后往前的读tmp=flag_data[i]for j in range(len(tmp)-2,-1,-2):num=int('0x'+tmp[j:j+2],16)flag_str+=chr(num)
print(flag_str)
#flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}

[安洵杯 2019]game

elf文件,无壳,ida分析
main函数调用的许多函数都有控制流平坦化混淆,用defalt.py脚本一个一个去平坦化
main函数,获取输入,general_inspection函数利用sudoku做一些运算,不太明白作用,不过影响不大,trace函数完全填充sudoku,动调可得到完全填充的结果,check函数没什么作用,check1函数对输入进行变换,最后进入check3函数验证输入
game-main
进入check1函数,对input进行变换,首先input前半部分和后半部分交换,然后input两个一组,两两交换,最后再对input进行变换,input最后的变换结果均为数字字符
game-check1
check3->check2函数,首先将变换后的input中的数字字符转成普通数字,存储到v11,然后v11顺序地填充到D0g3中元素为0的位置,未完全填充的D0g3也可通过动调得到,最后比较D0g3和sudoku
game-check2
动调得到未完全填充的D0g3和已完全填充的sudoku后,写逆运算脚本即可得到flag

#coding:utf-8
sudoku=[
1,4,5,3,2,7,6,9,8,
8,3,9,6,5,4,1,2,7,
6,7,2,8,1,9,5,4,3,
4,9,6,1,8,5,3,7,2,
2,1,8,4,7,3,9,5,6,
7,5,3,2,9,6,4,8,1,
3,6,7,5,4,2,8,1,9,
9,8,4,7,6,1,2,3,5,
5,2,1,9,3,8,7,6,4]
D0g3=[
1,0,5,3,2,7,0,0,8,
8,0,9,0,5,0,0,2,0,
0,7,0,0,1,0,5,0,3,
4,9,0,1,0,0,3,0,0,
0,1,0,0,7,0,9,0,6,
7,0,3,2,9,0,4,8,0,
0,6,0,5,4,0,8,0,9,
0,0,4,0,0,1,0,3,0,
0,2,1,0,3,0,7,0,4]
arr=[]
for i in range(81):if D0g3[i]==0:  #input填充到D0g3中元素为0的位置arr.append(sudoku[i])
for i in range(len(arr)):for j in range(32,128):#对input的第三次变换通过爆破来解if arr[i]+48==(j & 0xF3 | ~j & 0xC) - 20:arr[i]=j
for i in range(0,len(arr),2): #两个一组,两两交换arr[i],arr[i+1]=arr[i+1],arr[i]
arr[0:20],arr[20:40]=arr[20:40],arr[0:20]#input前半部分和后半部分交换
flag="".join(chr(i) for i in arr)
print(flag)
#KDEEIFGKIJ@AFGEJAEF@FDKADFGIJFA@FDE@JG@J

运行elf,输入,验证正确
game-right

[SCTF2019]Strange apk

apk文件,jadx-gui打开
主要逻辑在sctf.hello.c类中
data是apk自带的资源文件,在assets目录下可找到,先对data进行__方法处理,再进行_方法处理
strangeapk-logic
__方法就是读取data文件的字节
strangeapk-__
_方法是对data文件的字节进行0方法的处理,再将结果写到另一个文件中
strangeapk-_
0方法,可知是对data文件读取到的字节与"syclover"做循环异或运算,结果写到另一个文件中
在这里插入图片描述
脚本:

f= open("D:\\ctfdownloadfiles\\data", "rb")
res= open("D:\\ctfdownloadfiles\\res", "wb")
data=f.read()
s="syclover"
res_data=""
count=0
for c in data:res_data+=chr(ord(c)^ord(s[count%len(s)]))count+=1
res.write(res_data)
res.close()

将输出的文件后缀名改为apk后,再用jadx-gui分析
先看sctf.demo.myapplication.s类,验证输入的长度是否为30,对输入的前12个字符做base64编码后与已知字符串比较,后18个字符赋给data_return
strangeapk-s
再看sctf.demo.myapplication.t类,key为"syclover"的md5的十六进制摘要,输入的后18个字符与key作为参数传入f.encode方法,返回的字符串与已知字符串比较
strangeapk-t
再看sctf.demo.myapplication.f类,str为输入的后18个字符,长度s为18,key为"syclover"的md5的十六进制摘要,为"8bfc8af07bca146c937f283b8ec768d4",长度c为32,for循环中,t先append一个输入字符,再append一个key中的字符,由于f<s<c,故t从key中append的字符总是第0个字符,即’8’,同时也知道返回字符串中某字符的下标为偶数时,其即为输入的字符
strangeapk-f
写脚本即可得到flag

import base64
s=base64.b64decode("c2N0ZntXM2xjMG1l")
res="~8t808_8A8n848r808i8d8-8w808r8l8d8}8"
for i in range(0,len(res),2):s+=res[i]
print(s)
#sctf{W3lc0me~t0_An4r0id-w0rld}

[CFI-CTF 2018]IntroToPE

exe程序,运行后输入password,点击验证
查壳发现时.Net程序,用dnSpy打开
来到ValidatePasswd.verifyPasswd()方法,简单的base64编码验证
introtope-logic
解base64即可得到flag
introtope-flag

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

REVERSE-PRACTICE-BUUCTF-20

REVERSE-PRACTICE-BUUCTF-20[SCTF2019]creakme[网鼎杯 2020 青龙组]bang[WUSTCTF2020]funnyreDig the way[SCTF2019]creakme exe程序&#xff0c;运行后提示输入ticket&#xff0c;无壳&#xff0c;用ida分析 交叉引用字符串“please input your ticket:”来到sub_402540函数 …

Web Reference和Service Reference的区别

今天因为项目需要使用服务引用&#xff0c;就按之前的经验添加上了&#xff0c;步骤如下&#xff1a; 项目根目录——引用——右键——添加服务引用——高级——添加Web引用——输入接口的URL地址——回车&#xff08;下方出现的就是接口的定义的方法&#xff09;——修改Web引…

REVERSE-PRACTICE-BUUCTF-21

REVERSE-PRACTICE-BUUCTF-21[SCTF2019]babyre[MRCTF2020]EasyCpp[GUET-CTF2019]encrypt[QCTF2018]Xman-babymips[SCTF2019]babyre elf文件&#xff0c;无壳&#xff0c;用ida分析 在start函数中看到main函数的字样&#xff0c;但是左侧函数窗没有找到main函数 原因是main函数中…

原型设计工具——“墨刀”的介绍与基本教程

一、产品介绍 &#xff08;1&#xff09;产品简介&#xff1a; 墨刀是一款在线原型设计与协同工具&#xff0c;借助墨刀&#xff0c;产品经理、设计师、开发、销售、运营及创业者等用户群体&#xff0c;能够搭建为产品原型&#xff0c;演示项目效果。 &#xff08;2&#xf…

MockPlus原型设计介绍

在第八周的课堂上&#xff0c;王文娟老师在校园系统上发布了对于自行选择的原型设计软件进行资料查找以及自学的任务。因为之前的课程学习需要&#xff0c;我们已经大概掌握了原型设计软件Axure的使用&#xff0c;因此在这里&#xff0c;我选择了另一原型设计进行介绍&#xff…

REVERSE-PRACTICE-BUUCTF-22

REVERSE-PRACTICE-BUUCTF-22[SCTF2019]Who is he[FlareOn2]very_success[NPUCTF2020]Baby Obfuscation[HDCTF2019]MFC[SCTF2019]Who is he unity游戏&#xff0c;运行后输入&#xff0c;点击按钮检验输入 dnSpy打开Who is he\Who is he_Data\Managed\Assembly-CSharp.dll 在Te…

浅谈常见的NoSQL技术方案和选型

前言 在互联网和大数据的背景下&#xff0c;越来越多的网站、应用系统需要支撑 海量数据存储、高并发请求、高可用、高可扩展性 等特性要求。传统的 关系型数据库 已经难以应对类似的需求&#xff0c;各种各样的 NoSQL&#xff08;Not Only SQL&#xff09;数据库因此而产生。…

REVERSE-PRACTICE-BUUCTF-23

REVERSE-PRACTICE-BUUCTF-23[2019红帽杯]Snake[BSidesSF2019]blink[De1CTF2019]Re_Sign[ACTF新生赛2020]Splendid_MineCraft[2019红帽杯]Snake unity游戏&#xff0c;dnSpy打开Snake\Snake_Data\Managed\Assembly-CSharp.dll 发现要载入Interface这个dll ida打开Snake\Snake_…

REVERSE-PRACTICE-BUUCTF-24

REVERSE-PRACTICE-BUUCTF-24[watevrCTF 2019]Timeout[SUCTF2019]hardcpp[CISCN2018]2ex[UTCTF2020]babymips[watevrCTF 2019]Timeout elf文件&#xff0c;无壳&#xff0c;ida分析 main函数中signal&#xff0c;alarm&#xff0c;delay三个函数配合使用是为了反调试 交叉引用…

REVERSE-PRACTICE-BUUCTF-25

REVERSE-PRACTICE-BUUCTF-25特殊的 BASE64[FlareOn1]Javascrap[WMCTF2020]easy_re[NPUCTF2020]BasicASM特殊的 BASE64 exe程序&#xff0c;运行后输入&#xff0c;无壳&#xff0c;ida分析 main函数&#xff0c;读取输入&#xff0c;进行变表base64编码&#xff0c;与rightFla…

REVERSE-PRACTICE-BUUCTF-26

REVERSE-PRACTICE-BUUCTF-26[FlareOn6]FlareBear[SUCTF2018]babyre[GKCTF2020]WannaReverse[FlareOn4]greek_to_me[FlareOn6]FlareBear apk文件&#xff0c;模拟器上运行&#xff0c;创建一个小熊&#xff0c;有三种方式交互&#xff0c;分别为“吃饭”&#xff0c;“篮球”以…

C#的变迁史02 - C# 2.0篇

在此重申一下&#xff0c;本文仅代表个人观点&#xff0c;如有不妥之处&#xff0c;还请自己辨别。 第一代的值类型装箱与拆箱的效率极其低下&#xff0c;特别是在集合中的表现&#xff0c;所以第二代C#重点解决了装箱的问题&#xff0c;加入了泛型。1. 泛型 - 珍惜生命&#x…

REVERSE-PRACTICE-BUUCTF-27

REVERSE-PRACTICE-BUUCTF-27[XMAN2018排位赛]Dragon Quest[羊城杯 2020]easyre[watevrCTF 2019]Repyc[2019红帽杯]calc[XMAN2018排位赛]Dragon Quest elf文件&#xff0c;无壳&#xff0c;ida分析 main函数&#xff0c;读取输入&#xff0c;start_quest函数验证输入&#xff0…

C#的变迁史03 - C# 3.0篇

C# 3.0 (.NET 3.5, VS2008) 第三代C#在语法元素基本完备的基础上提供了全新的开发工具和集合数据查询方式&#xff0c;极大的方便了开发。 1. WPF&#xff0c;WCF&#xff0c;WF 这3个工程类型奠定了新一代.NET开发的客户端模型&#xff0c;通信模型&#xff0c;工作流模型。 …

REVERSE-PRACTICE-BUUCTF-28

REVERSE-PRACTICE-BUUCTF-28[FlareOn6]Memecat Battlestation[b01lers2020]chugga_chugga[INSHack2018]Tricky-Part1[watevrCTF 2019]esreveR[FlareOn6]Memecat Battlestation .Net程序&#xff0c;运行后输入weapon code&#xff0c;用dnSpy打开 在Stage1Form直接找到第一个w…

C#的变迁史04 - C# 4.0 之多线程篇

在.NET 4.0中&#xff0c;并行计算与多线程得到了一定程度的加强&#xff0c;这主要体现在并行对象Parallel&#xff0c;多线程Task&#xff0c;与PLinq。这里对这些相关的特性一起总结一下。 使用Thread方式的线程无疑是比较麻烦的&#xff0c;于是在这个版本中有了改善的版本…

REVERSE-PRACTICE-BUUCTF-29

REVERSE-PRACTICE-BUUCTF-29[FlareOn1]Shellolololol[CFI-CTF 2018]powerPacked[INSHack2018]Tricky-Part2[CFI-CTF 2018]Automated Reversing[FlareOn1]Shellolololol exe程序&#xff0c;直接不能运行&#xff0c;无壳&#xff0c;ida分析 简单F8单步调试发现&#xff0c;在…

C#的变迁史05 - C# 4.0篇

C# 4.0 (.NET 4.0, VS2010) 第四代C#借鉴了动态语言的特性&#xff0c;搞出了动态语言运行时&#xff0c;真的是全面向“高大上”靠齐啊。 1. DLR动态语言运行时 C#作为静态语言&#xff0c;它需要编译以后运行&#xff0c;在编译的过程中&#xff0c;编译器要检查语法的正确性…

REVERSE-PRACTICE-BUUCTF-30

REVERSE-PRACTICE-BUUCTF-30[RCTF2019]DontEatMe[b01lers2020]little_engine[NPUCTF2020]你好sao啊[MRCTF2020]Shit[RCTF2019]DontEatMe exe程序&#xff0c;运行后输入&#xff0c;无壳&#xff0c;用ida分析 交叉引用字符串来到sub_401260函数&#xff0c;读取输入&#xff…

C#的变迁史06 - C# 4.0 之并行处理篇

前面看完了Task对象&#xff0c;这里再看一下另一个息息相关的对象Parallel。 Parallel对象 Parallel对象封装了能够利用多核并行执行的多线程操作&#xff0c;其内部使用Task来分装多线程的任务并试图将它们分配到不同的内核中并行执行。请注意“试图”这个词&#xff0c;Par…