REVERSE-PRACTICE-BUUCTF-13

REVERSE-PRACTICE-BUUCTF-13

    • firmware
    • [ACTF新生赛2020]Oruga
    • [Zer0pts2020]easy strcmp
    • [GXYCTF2019]simple CPP

firmware

.bin(二进制)文件,由题目提示知是路由器固件逆向
参考:逆向路由器固件之解包 Part1
linux安装好binwalk和firmware-mod-kit
binwalk会分析二进制文件中可能的固件头或者文件系统,然后输出识别出的每个部分以及对应的偏移量
binwalk该二进制文件,发现包含了squashfs文件系统(squashfs是linux下的一种只读压缩文件系统类型)
firmware-binwalk
binwalk -e 该二进制文件,提取出各部分数据到各个文件,相当于解压固件,解压出来的文件放在当前目录的/_firmware.bin.extracted文件夹下(注意此时的suqashfs-root文件夹是否为空)
firmware-binwalk-e
使用firmware-mod-kit解包提取出来的squashfs文件
/*******************************************************
firmware-mod-kit的一些用法:
extract-firmware.sh 解包固件
build-firmware.sh 重新封包
check_for_upgrade.sh 检查更新
unsquashfs_all.sh 解包提取出来的squashfs文件
*******************************************************/
firmware-fmk
解包squashfs文件出来的文件放在了当前目录的squashfs-root-1文件夹中
(实际上,在本人虚拟机binwalk -e 该二进制文件后,生成文件夹/_firmware.bin.extracted中的squashfs-root文件夹,已经是解包squashfs文件出来的文件夹了,即squashfs-root文件夹和squashfs-root-1文件夹中包含的文件是相同的,如果squashfs-root文件夹下内容为空,是由于sasquatch安装有问题导致的,可以通过重新安装sasquatch解决,参考:dir815_FW_102.bin路由器固件解压碰到的坑)
firmware-fmk-res
在/_firmware.bin.extracted/squashfs-root/tmp目录或/_firmware.bin.extracted/squashfs-root-1/tmp目录下有一个backdoor文件
backdoor查壳发现有upx壳,脱壳后拖入ida分析
在字符串窗口找到网址
firmware-address
交叉引用网址,在initConnection函数中找到端口
firmware-port

[ACTF新生赛2020]Oruga

elf文件,无壳,ida分析
main函数逻辑清晰,获取输入,检验输入是否为“actf{”开头,验证输入内容,以及最后一个字符是否为“}”
oruga-logic
进入check函数,分析可知是一个16x16的迷宫,和常规迷宫的按一次方向键则往该方向前进一格的机制不同,该迷宫的前进机制为,按一次方向键,则往该方向一直前进,直到撞到墙,具体分析知道,在map为零的位置时,可以持续前进,到达第一个非零的位置就停下来,然后减一个步长回到前一个零的位置,再读input的内容更新步长,更新步长实际上就是换方向

_BOOL8 __fastcall check(__int64 input)
{int index; // [rsp+Ch] [rbp-Ch]signed int input_index; // [rsp+10h] [rbp-8h]signed int step; // [rsp+14h] [rbp-4h]index = 0;input_index = 5;step = 0;while ( map[index] != '!' )                   // 终点为"!"{index -= step;                              // 由第48行代码可知,由于index叠加走到了非零的位置,这时需要减一个步长,回到前一个零位置if ( *(_BYTE *)(input_index + input) != 'W' || step == -16 )// 由input的内容决定步长step{if ( *(_BYTE *)(input_index + input) != 'E' || step == 1 ){if ( *(_BYTE *)(input_index + input) != 'M' || step == 16 ){if ( *(_BYTE *)(input_index + input) != 'J' || step == -1 )return 0LL;step = -1;                            // J-左}else{step = 16;                            // M-下}}else{step = 1;                               // E-右}}else{step = -16;                               // W-上}++input_index;                              // 读下一个input的字符while ( !map[index] )                       // 该while循环体只能在map[index]=='0'时执行{if ( step == -1 && !(index & 0xF) )       // 判断边界的四个ifreturn 0LL;if ( step == 1 && index % 16 == 15 )return 0LL;if ( step == 16 && (unsigned int)(index - 240) <= 0xF )return 0LL;if ( step == -16 && (unsigned int)(index + 15) <= 0x1E )return 0LL;index += step;                            // index按照当前的步长循环叠加,即按下一个方向键,就会沿着这个方向一直走,直到第一个非零的位置停下}}return *(_BYTE *)(input_index + input) == '}';
}

把map提取出来,制成16x16的迷宫,按照前进机制走完迷宫即可,起始点为左上角的[0,0],终止点为“!”(0x21),W-上,M-下,J-左,E-右,路线即为flag
oruga-flag

[Zer0pts2020]easy strcmp

elf文件,无壳,ida分析
main函数,有一个比较字符串的if语句决定输出的内容,其他什么也没有
easystrcmp-logic
来到start函数,发现在调用main函数前,先调用了fini函数和init函数
easystrcmp-start
fini函数直接返回了,分析init函数,可以知道,在调用main函数前,程序将.init_array段地址到.fini_array段地址之间的函数全部执行一遍,命令行参数作为段之间函数的参数
easystrcmp-init
这里可以看到,.init_array段和.fini_array段之间有3个函数,依次分析知道,重要的是sub_795函数
easystrcmp-segfunc
sub_795->sub_6EA,分析sub_6EA函数,计算输入的长度,将输入的内容顺序地与qword_201060数组的元素相减,然后去到main函数和那段字符串比较
easystrcmp-sub_6EA
写脚本即可得到flag
easystrcmp-script

[GXYCTF2019]simple CPP

exe程序,运行后提示输入flag,输入错误退出程序,无壳,ida分析
交叉引用字符串来到sub_140001290函数

__int64 sub_140001290()
{bool v0; // si__int64 v1; // rax__int64 v2; // r8unsigned __int8 *v3; // raxunsigned __int8 *v4; // rbxint v5; // er10__int64 v6; // r11_BYTE *input_copy; // r9void **v8; // r8__int64 arr[3]; // rdi__int64 arr[2]; // r15__int64 arr[1]; // r12__int64 arr[0]; // rbpsigned int v13; // ecxunsigned __int8 *v14; // rdx__int64 v15; // rdi__int64 *v16; // r14__int64 v17; // rbp__int64 v18; // r13_QWORD *v19; // rdi__int64 v20; // r12__int64 v21; // r15__int64 v22; // rbp__int64 v23; // rdx__int64 v24; // rbp__int64 v25; // rbp__int64 v26; // r10__int64 v27; // rdi__int64 v28; // r8bool v29; // dl__int64 v30; // raxvoid *v31; // rdxconst char *v32; // rax__int64 v33; // rax_BYTE *v34; // rcx__int64 v36; // [rsp+20h] [rbp-68h]void *input; // [rsp+30h] [rbp-58h]unsigned __int64 input_len; // [rsp+40h] [rbp-48h]unsigned __int64 v39; // [rsp+48h] [rbp-40h]v0 = 0;input_len = 0i64;v39 = 15i64;LOBYTE(input) = 0;LODWORD(v1) = printf(std::cout, "I'm a first timer of Logic algebra , how about you?");std::basic_ostream<char,std::char_traits<char>>::operator<<(v1, sub_140001B90);printf(std::cout, "Let's start our game,Please input your flag:");sub_140001DE0(std::cin, &input, v2);          // 读取inputstd::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140001B90);if ( input_len - 5 > 25 )                     // input不需要GXY{}包住{LODWORD(v33) = printf(std::cout, "Wrong input ,no GXY{} in input words");std::basic_ostream<char,std::char_traits<char>>::operator<<(v33, sub_140001B90);goto LABEL_45;}v3 = sub_1400024C8(32ui64);                   // 开辟一块大小为32的,元素类型为unsigned int8的地址空间给v3v4 = v3;if ( v3 )                                     // 新开辟的地址空间全部赋0值{*v3 = 0i64;*(v3 + 1) = 0i64;*(v3 + 2) = 0i64;*(v3 + 3) = 0i64;}else{v4 = 0i64;}v5 = 0;if ( input_len > 0 ){v6 = 0i64;do{input_copy = &input;if ( v39 >= 16 )input_copy = input;v8 = &Dst;if ( qword_140006060 >= 0x10 )v8 = Dst;                               // Dst="i_will_check_is_debug_or_not",长度为28v4[v6] = input_copy[v6] ^ *(v8 + v5++ % 27);// input和Dst异或,结果放入v4++v6;}while ( v5 < input_len );}arr[3] = 0i64;arr[2] = 0i64;arr[1] = 0i64;arr[0] = 0i64;if ( input_len > 30 )                         // input长度验证goto LABEL_28;v13 = 0;if ( input_len <= 0 )goto LABEL_28;v14 = v4;                                     // v14=v4,是input和Dst异或的结果do                                            // do循环体,实际上是把v14分成四段,前三段长度为8,分别放入v12,v11,v10中,剩下的放在v9// 依次记为arr[0],arr[1],arr[2],arr[3],重要的是算出arr[0~3]{v15 = *v14 + arr[3];++v13;++v14;switch ( v13 ){case 8:arr[0] = v15;goto LABEL_24;case 16:arr[1] = v15;goto LABEL_24;case 24:arr[2] = v15;
LABEL_24:v15 = 0i64;break;case 32:printf(std::cout, "ERRO,out of range");exit(1);break;}arr[3] = v15 << 8;}while ( v13 < input_len );if ( arr[0] ){v16 = sub_1400024C8(32ui64);*v16 = arr[0];                              // arr[0~3]放入v16[0~3]中v16[1] = arr[1];v16[2] = arr[2];v16[3] = arr[3];goto LABEL_29;}
LABEL_28:v16 = 0i64;
LABEL_29:v36 = v16[2];                                 // v36=arr[2]v17 = v16[1];                                 // v17=arr[1]v18 = *v16;                                   // v18=arr[0]v19 = sub_14000223C(32ui64);                  // 开辟一块大小为32的,元素类型为unsigned int8的地址空间给v19if ( IsDebuggerPresent() )                    // 反调试{printf(std::cout, "Hi , DO not debug me !");Sleep(0x7D0u);exit(0);}v20 = v17 & v18;                              // v20=arr[1]&arr[0]*v19 = v17 & v18;                             // v19[0]=arr[1]&arr[0]v21 = v36 & ~v18;                             // v21=arr[2]&(~arr[0])v19[1] = v21;                                 // v19[1]=arr[2]&(~arr[0])v22 = ~v17;                                   // v22=~arr[1]v23 = v36 & v22;                              // v23=arr[2]&(~arr[1])v19[2] = v36 & v22;                           // v19[2]=arr[2]&(~arr[1])v24 = v18 & v22;                              // v24=arr[0]&(~arr[1])v19[3] = v24;                                 // v19[3]=arr[0]&(~arr[1])if ( v21 != 0x11204161012i64 )                // 验证v19[1]==0x11204161012,即arr[2]&(~arr[0])==0x11204161012{v19[1] = 0i64;v21 = 0i64;}v25 = v21 | v20 | v23 | v24;                  // 需v25==0x3E3A4717373E7F1F成立,即(arr[2]&(~arr[0])) | (arr[1]&arr[0]) | (arr[2]&(~arr[1])) | (arr[0]&(~arr[1]))==0x3E3A4717373E7F1Fv26 = v16[1];                                 // v26=arr[1]v27 = v16[2];                                 // v27=arr[2]v28 = v23 & *v16 | v27 & (v20 | v26 & ~*v16 | ~(v26 | *v16));// (arr[2]&(~arr[1])) & (arr[0]) | (arr[2]) & ((arr[1]&arr[0]) | (arr[1]) & ~(arr[0]) | ~((arr[1]) | (arr[0])))==0x8020717153E3013v29 = 0;if ( v28 == 0x8020717153E3013i64 )            // 由第171行代码可知,v0需要为1,v28==0x8020717153E3013成立v29 = v25 == 0x3E3A4717373E7F1Fi64;         // 验证v25==0x3E3A4717373E7F1F,相等返回1,不等返回0if ( (v25 ^ v16[3]) == 0x3E3A4717050F791Fi64 )// v16[3]=arr[3],即arr[3]^0x3E3A4717373E7F1F==0x3E3A4717050F791Fv0 = v29;                                   // v0为v25==0x3E3A4717373E7F1F的返回值,等式成立返回1,不等返回0if ( (v21 | v20 | v26 & v27) != (~*v16 & v27 | 0xC00020130082C0Ci64) || v0 != 1 )// 需要v0为1,意味着v25==0x3E3A4717373E7F1F成立且((arr[2]&(~arr[0])) |(arr[1]&arr[0]) | (arr[1]) & (arr[2])) == (~(arr[0])& (arr[2]) | 0xC00020130082C0C){printf(std::cout, "Wrong answer!try again");j_j_free(v4);}else{LODWORD(v30) = printf(std::cout, "Congratulations!flag is GXY{");// input不需要GXY{}包住v31 = &input;if ( v39 >= 16 )v31 = input;v32 = sub_140001FD0(v30, v31, input_len);printf(v32, "}");j_j_free(v4);}
LABEL_45:if ( v39 >= 0x10 ){v34 = input;if ( v39 + 1 >= 0x1000 ){v34 = *(input - 1);if ( (input - v34 - 8) > 0x1F )invalid_parameter_noinfo_noreturn();}j_j_free(v34);}return 0i64;
}

写解arr[0~3]的脚本
simplecpp-script
写逆异或运算得到flag的脚本,由flag的明文字符串可知,arr[1]的结果错误,原因是原方程组有多组解,参考别的师傅的wp,比赛给出了第二部分的flag,e!P0or_a,替换掉错误的8个字符,结果为We1l_D0ne!P0or_algebra_am_i
simplecpp-script

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

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

相关文章

REVERSE-PRACTICE-BUUCTF-14

REVERSE-PRACTICE-BUUCTF-14[FlareOn3]Challenge1[GUET-CTF2019]number_game[GWCTF 2019]re3[网鼎杯 2020 青龙组]singal[FlareOn3]Challenge1 exe程序&#xff0c;运行后提示输入密码&#xff0c;输入错误退出程序&#xff0c;无壳&#xff0c;ida分析 main函数逻辑清晰&…

REVERSE-PRACTICE-BUUCTF-15

REVERSE-PRACTICE-BUUCTF-15[2019红帽杯]xx[ACTF新生赛2020]Universe_final_answer[WUSTCTF2020]level4findKey[2019红帽杯]xx exe程序&#xff0c;运行后直接输入&#xff0c;无壳&#xff0c;ida分析 交叉引用字符串“You win&#xff01;”来到sub_1400011A0函数 主要的逻辑…

【三层架构】——COM/DCOM初识

背景&#xff1a; 在学习三层架构的时候&#xff0c;知道三层分为UI层&#xff08;表现层&#xff09;、BLL层&#xff08;业务逻辑层&#xff09;、DAL层&#xff08;数据访问层&#xff09;&#xff0c;相对于传统的二层架构&#xff08;客户端和数据库&#xff09;来说&…

REVERSE-PRACTICE-BUUCTF-16

REVERSE-PRACTICE-BUUCTF-16[UTCTF2020]basic-reequation[安洵杯 2019]crackMe[FlareOn5]Minesweeper Championship Registration[UTCTF2020]basic-re elf文件&#xff0c;无壳&#xff0c;用ida分析 main函数就是简单的加减乘除运算 shiftF12&#xff0c;在字符串窗口看到fla…

IPC之命名管道

1.管道是通过IO接口存取得字节流&#xff0c; windows中利用得是ReadFile()和WriteFile(),windows利用单一句柄支持双向IO,命名管道也称做FIFO(first in first out) 命名管道得机制&#xff1a;一个进程把数据放到管道里&#xff0c;另一个知道管道名字得进程把数据把取走&…

REVERSE-PRACTICE-BUUCTF-17

REVERSE-PRACTICE-BUUCTF-17[网鼎杯 2020 青龙组]jocker[2019红帽杯]childRE[MRCTF2020]PixelShooter[ACTF新生赛2020]SoulLike[网鼎杯 2020 青龙组]jocker exe程序&#xff0c;运行后提示输入flag&#xff0c;无壳&#xff0c;用ida分析 main函数平衡栈后&#xff0c;F5反汇编…

Excluding Files From Team Foundation Version Control Using .tfignore Files

At one point I was coding on a hobby project, using Visual Studio Online for project management and source control. Because of the technologies involved, a large number of temporary files were being generated that I didn’t want checked in. Visual Studio’…

REVERSE-PRACTICE-BUUCTF-18

REVERSE-PRACTICE-BUUCTF-18[SWPU2019]ReverseMe[FlareOn1]Bob Doge[FlareOn5]Ultimate Minesweeper[GKCTF2020]Chellys identity[SWPU2019]ReverseMe exe程序&#xff0c;运行后提示输入flag&#xff0c;输入错误打印“Try again”&#xff0c;无壳&#xff0c;ida分析 交叉引…

VS2008中Web Reference和Service Reference的区别

很早就发现在vs2008中应用web service有两种方式&#xff0c;即Add Web Reference和Add Service Reference&#xff0c;但是一直不是很清楚这两者有什么区别。趁着今天有空实验一下这两者的区别并记录下来供大家参考。 首先在网上查找&#xff0c;发现有如下两个主要区别&#…

REVERSE-PRACTICE-BUUCTF-19

REVERSE-PRACTICE-BUUCTF-19[RoarCTF2019]polyre[安洵杯 2019]game[SCTF2019]Strange apk[CFI-CTF 2018]IntroToPE[RoarCTF2019]polyre elf文件&#xff0c;无壳&#xff0c;用ida分析 main函数的结构&#xff0c;多重循环&#xff0c;是控制流平坦化&#xff0c;参考&#xf…

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…