load3r

题目提示可知bin文件为bootloader
将其用IDA打开,选择16-bit模式加载,即可看到反汇编出的程序

由于IDA不支持16-bit的F5,所以只能读汇编
不过由于bootloader对长度有限制,必须为512字节以内,因此相对不是很复杂
多提一句,按空格可以转为graph模式,这个状态下可以看到代码块之间的跳转关系,非常方便

seg000:000B                 mov     si, 16h
seg000:000E                 call    sub_11B

为例分析,双击sub_11B进去看这个函数

int x是系统提供的中断API,这个函数中IDA对int 10H进行了提示:
WRITE CHARACTER AND ADVANCE CURSOR
即写出字符,其中AL寄存器保存字符,BH和BL表示颜色和坐标等高级选项,可以不用关心
而AL的赋值来自于lodsb,百度它可以发现这条汇编指令的作用是将si寄存器指向的地址处的值送到AL中,然后si寄存器自增。
而si寄存器在call之前进行了赋值,即0x16h处的字符串"'ENTER THE FLAG"

int 10h之后是jmp回函数开头,因此这是一个循环
而循环的终止条件就在于cmp al, 0和jz 0x1d3两条指令,
它们表示当AL为0时跳转到0x1d3处

那么到这里就可以判断出sub_11B这个函数就是用来打印字符串的,我们将光标移动到它上,按"n"可以重命名,从而方便以后的观察

继续往后分析,在sub_128中,int 16h来接收输入

seg000:012E                 int     16h             ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY
seg000:012E                                         ; Return: AH = scan code, AL = character
seg000:0130                 mov     ds:6Dh, al
seg000:0133                 mov     [bx+6Fh], al
seg000:0137                 cmp     byte ptr ds:6Dh, 0Dh
seg000:013C                 jz      short loc_147

调用完后al存储字符的ASCII,后面将它放入ds:6D和[bx+6Fh]中,再与0D比较,相等则跳转
对照ASCII表可知,0x0d是回车键,也就是说直到输入回车表示结束

不跳转的情况下也是一个循环,会对bx自增,而调用之前可知bx的初值为0(在0x5处的指令mov bx, 0),因此bx是个计数器

结束输入以后

seg000:014D                 cmp     bx, 22h ; '"'
seg000:0150                 jz      short loc_154
seg000:0152                 jmp     short loc_184

可以看到对输入字符数进行了检查,非0x2 2的话会进入0x184分支,而在这个分支

seg000:018A                 mov     si, 65h ; 'e'
seg000:018D                 call    print

打印了一串字符串,即0x65处的“Noooo"
所以这里是错误结果

继续往另一边看,

seg000:015D loc_15D:                                ; CODE XREF: sub_128+4A↓j
seg000:015D                                         ; sub_128+54↓j
seg000:015D                 mov     al, 31h ; '1'
seg000:015F                 cmp     [bx+0C9h], al
seg000:0163                 jz      short loc_174

这里是bx作为index,将[0xc9+index]处的值(即"0100010011011101111111011010110101")与0x31即(‘1’)比较
然后做了一个分支,jz即相等的时候,会调用shl ax,1,即将ax左移1位
不等的时候则会调用shr ax,1,即将ax右移1位
然后结果存到0xee+bx中,再将bx+1,回头循环

这里的ax同样来自于lodsb,那么要去找si寄存器的值,即

seg000:015A                 mov     si, 6Fh ; 'o'

这里0x6f存的值就是刚才int 16h接收的输入

等于"0"的那个分支中还对计数器bx做了检查,等于0x23的时候停止循环,继续往下走

seg000:01AE loc_1AE:                                ; CODE XREF: sub_128+94↓j
seg000:01AE                 lodsb
seg000:01AF                 cmp     al, 0
seg000:01B1                 jz      short loc_1BE
seg000:01B3                 mov     ah, 0Eh
seg000:01B5                 xor     al, 5
seg000:01B7                 mov     [bx+9Ch], al
seg000:01BB                 inc     bx
seg000:01BC                 jmp     short loc_1AE

这里结构也类似,只是逐字符xor 5,百度即可知道是异或运算

最后

seg000:01BE loc_1BE:                                ; CODE XREF: sub_128+89↑j
seg000:01BE                 mov     bx, 21h ; '!'
seg000:01C1                 mov     si, 9Ch
seg000:01C4
seg000:01C4 loc_1C4:                                ; CODE XREF: sub_128+A9↓j
seg000:01C4                 lodsb
seg000:01C5                 cmp     al, [bx+27h]
seg000:01C9                 jnz     short loc_184
seg000:01CB                 cmp     bx, 0
seg000:01CE                 jz      short loc_192
seg000:01D0                 dec     bx
seg000:01D1                 jmp     short loc_1C4

与0x27处的字符比较
注意这里的bx是倒着用的,初值为0x21,每次比较过后dec即自减

不等的话会通过jnz跳转到失败分支0x184

综上
整个逻辑等价于

char input[0x22];
char data_ee[0x22];
char data_27[] = "w2g1kS<c7me3keeuSMg1kSk%Se<=S3%/e/";
char data_c9[] = "0100010011011101111111011010110101";
scanf("%s", &input);
if(len(input)==0x22){
for(int bx=0;bx<0x23;bx++){
if(data_c9[bx]=='1'){
data_ee = input[bx]<<1;
}
else{
data_ee = input[bx]>>1;
}
}
for(int bx=0;bx<0x23;bx++){
data_ee[bx] = data_ee[bx]^5;
}
for(int bx=0x21;bx==0;bx--){
if(data_ee[bx]!=data_27[bx]){
wrong();
}
}
correct();
}
wrong();

即先根据data_c9判断将输入左移或右移1位,然后全部异或5,最后与data_27比较

求解正确输入的方法很简单,只需要逆着来一遍即可,先将data_27异或5,然后再左移或右移1位

python3代码如下:

a = "0100010011011101111111011010110101"
b = 'w2g1kS<c7me3keeuSMg1kSk%Se<=S3%/e/'[::-1]
for i in range(len(a)):v = ord(b[i])^5if(a[i]=="0"):c = v<<1else:c = v>>1print(chr(c),end='')

C代码也很好写,我就懒得折腾了

最后如果得到
“T0T@l+pr0+@7+7h1$+8007l04d3r+7h1n9”
就说明对咯~

Decoy

题目描述玄乎的一批,难度还是Medium,上面的load3r才是Easy

The closer you think you are, the less you’ll actually see.

main函数里直接进行接收输入并check
可以看到有很多路径,扫一眼cfg相当好看

随便选一条路径走下去发现是将input分了四段进行check
最后通过的话会落到sub_4015a6里,然后里面混淆了两段字符串
通过IDC脚本快速解出

IDC>auto i;for(i=0;i<=0x29;i++){Message("%c", Byte(0x407078+i)^1);}
Y0u_Thought_You_Can_Solve_This_Decoy??? : P
IDC>auto i;for(i=0;i<=0x1a;i++){Message("%c", Byte(0x4070a3+i)^1);}
Try_A_Different_Approach_: P

很明显,这是错误的路径
那么问题就在于找出正确的路径了

直接看F5相对而言不太好分清深度,我们来看CFG
将那几个操蛋的函数重命名以后,在graph view模式下可以方便地看到与FakeCorrect和TinyMistake同一层级的代码块

扫一下就能发现这里

这一行的代码块call的目标都是深蓝色的命名函数,只有这个东西与众不,让我们来看看它是什么妖精
还是同样的字符串混淆

IDC>auto i;for(i=0;i<=0x6;i++){Message("%c", Byte(0x4070c2+i)^2);}
correct

那么稳啦,就是这个路径了,于是再回溯找出各个函数的结果吧
以第一个函数为例

int __cdecl sub_4018D9(int a1)
{char v2[12]; // [esp+8h] [ebp-28h]char v3[12]; // [esp+14h] [ebp-1Ch]int v4; // [esp+20h] [ebp-10h]int v5; // [esp+24h] [ebp-Ch]int j; // [esp+28h] [ebp-8h]int i; // [esp+2Ch] [ebp-4h]j = 0;v5 = 0;v4 = 0;for ( i = 0; i <= 10; ++i )v3[i] = *(_BYTE *)(i + a1) ^ 0xB;for ( i = 0; i <= 10; ++i )v3[i] ^= 0x13u;for ( j = 0; j <= 10; ++j )v2[j] = aFWlgL[j] ^ 0xB;v2[j] = 0;while ( v5 <= 10 ){if ( v3[v5] == v2[v5] )++v4;elsev4 = 0;++v5;}return v4;
}

a1是参数即input的指针,将input^0xB,再^0x13后与^0xB的str逐字符比较
那么很容易就能看出,只要将那串str异或0xB就能得到这一段输入啦

IDC>auto i;for(i=0;i<=10;i++){Message("%c", Byte(0x4070ca+i)^0x13);}
0und_Th3_n3

这就是这一段的内容了

最后将若干段解码出来的内容全部拼接起来即是flag啦

注意有一个函数的解码是逆序的哦

另外,除了在CFG中根据深度来找的方法,这个方法还是有点麻烦
还可以查看Functions Call的图(快捷键F12,View-Graph-Functions call)

这里可以看到,调用puts、putchar、printf三种输出函数的就那么几个
除了我们已经标好的FakeCorrect、Wrong、TinyMistake以外,全部都指向了sub_40166C

于是也能快速找到这个函数
初次以外,还有一些进阶的、使用脚本的方法来完成
例如如果每个分支调用的FakeCorrect都是函数名不一样的函数该怎么办呢?

这种时候可以通过脚本逐汇编判断,向下爬取,找到call的函数后提取特征,例如对整个函数哈希,然后给出地址和结果

而这实际上就是符号执行的思路了,因此也可以直接拿现成的框架,比如angr来跑

181008 逆向-inctf(load3r、Decoy)相关推荐

  1. 181010 逆向-inctf(ultimateGo)

    整体思路和切入点 看标题大概就能猜出来是Go语言 IDA加载进去看,还是没符号的Go语言逆向-- 之前做到有符号的是从main.main函数入手,现在连符号都没有,只好从字符串突破了 运行发现有输入提 ...

  2. 《人类简史》为什么消费主义喜欢讲故事?

    为什么社会发展会让人类更痛苦? 就算是濒临绝种的野生犀牛,比起被关在小格子里变肥.等着成为鲜美牛排的肉牛,日子应该还是好过得多.虽然自己的物种即将灭绝,但这丝毫不会影响那头野生犀牛对自己生活的满意程度 ...

  3. 正向最大匹配 和逆向最大匹配对比比较

    正向最大匹配法 &逆向最大匹配法 原理对比 下面介绍的分词算法中最简单的正向最大匹配和反向最大匹配. 这种两种方法都是机械分词方法,它是按照一定的策略将待分析的汉字串与一个"充分大的 ...

  4. 同向逆向、多车道线检测

    同向逆向.多车道线检测 输入输出接口 Input: (1)左右两个摄像头采集的实时图像视频分辨率(整型int) (2)左右两个摄像头采集的实时图像视频格式 (RGB,YUV,MP4等) (3)摄像头标 ...

  5. asp.net webform 复制窗体代码_逆向分析流氓软件自我复制以及防御思路

    一.前言 好长时间没有投稿了,之前被发布的稿件,也收到了Freebuf的现金奖励,同时陆陆续续收到好多圈类人士的夸奖,备受鼓舞,觉得自己应该坚持投稿,为安全事业略尽绵薄之力!最近任务不重,正好有时间投 ...

  6. iOS逆向(1)——利用ipa重签名,3分钟iPhone安装多个微信

    本文要达成如图效果,在一台iPhone上安装第二个微信: 准备: Xcode 微信ipa(可通过iTool进行下载) 重签名脚本 步骤 打开Xcode,新建Single View App项目,名字可以 ...

  7. iOS逆向(4)-代码注入,非越狱窃取微信密码

    利用LLDB对微信进行分析,然后利用分析的结果,再逐步讲解如何Hook微信的登录过程,截获微信密码. 在上一篇文章(APP重签名)中,已经介绍了如何对APP重签名,并且利用XCode将微信跑起来,既然 ...

  8. android逆向分析概述_Android存储概述

    android逆向分析概述 Storage is this thing we are all aware of, but always take for granted. Not long ago, ...

  9. Android逆向--如何调试smali代码?

    最近在重整Android逆向分析环境,一切都在从零开始,做下记录,给大家分享. 本文介绍Android逆向中smali代码的调试及环境的准备. 事先准备如下工具: Android killer:反编译 ...

  10. Android逆向之调试smali代码基础

    点击上方↑↑↑蓝字[协议分析与还原]关注我们 " 介绍Android逆向中调试smali代码的方法." 最近在重整Android逆向分析环境,一切都在从零开始,做下记录,给大家分享 ...

最新文章

  1. 特征工程 - 特征筛选
  2. 输入两个整数a和b,计算a+b的和
  3. IHttpHandler的学习(0-2)
  4. C# Graphic 绘制圆、三角形、椭圆、图片
  5. antv图例出现分页_带图例、文本的饼图
  6. 在使用ToolBar + AppBarLayout,实现上划隐藏Toolbar功能,遇到了一个坑。
  7. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
  8. 如果数组的值都一样java_java – 将数组中的相同值合并在一起
  9. 01 Oracle 导入SQL文件
  10. 为博聆网用户编写的userscript
  11. CSDN 创始人蒋涛:开源吞噬世界,得开发者得天下
  12. 玩客云安装mysql_玩客云的使用经验总结
  13. Arcgis连接sql server发布地图服务详解
  14. Automatic Targetless LiDAR-CameraCalibration: A Survey论文解读
  15. HDMI切换器的各种版本能不能互通?
  16. 可以搜索相似网站的网站
  17. USACO 2.1 健康的荷斯坦奶牛 Healthy Holsteins
  18. 007:Scrapy核心架构和高级运用
  19. 基于vb的mysql管理系统代码_基于VB+MySQL的简单图书管理系统
  20. 补码一位乘法(Booth算法)

热门文章

  1. 纯真IP数据库格式详解(转)
  2. 方框加对勾怎么输入_如何打出带方框的对号
  3. OVM Manager
  4. QChart修改标题颜色,修改X轴Y轴字体颜色
  5. Echarts图表隐藏X轴和Y轴
  6. 2022年下半年网络工程师上午真题及答案解析
  7. 自动登录QQ邮箱程序代码
  8. 电动车 碟刹维修 液体的杠杆原理, 帕斯卡定律
  9. 华为云 CentOS 镜像源配置
  10. 有赞订单导出的配置化实践