XCTF-攻防世界CTF平台-Reverse逆向类——57re5-packed-movement
Posted 大灬白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XCTF-攻防世界CTF平台-Reverse逆向类——57re5-packed-movement相关的知识,希望对你有一定的参考价值。
先查看文件信息:
是linux下的32位ELF文件,且被加了UPX的壳
下载最新版的UPX脱壳,UPX脱壳的Githup地址:https://github.com/upx/upx/releases/tag/v3.91
之后脱壳,指定加壳文件57,输出脱壳文件57move
upx -d 57 -o 57move
赋执行权限运行程序:
用IDA打开57move,找到字符串“Guess a flag:”
有两个位置使用了这个字符串:
同样地,我们查看“Wrong Flag!”字符串:
发现有70个引用的地方。
但是我们可以看到程序的汇编代码全都是mov,肯定是被混淆过了,这里是用了movfuscator来混淆,。
剑桥大学的Stephen Dolan证明了x86的mov指令是图灵完全的(论文《mov is Turing-complete》)。这意味着从理论上来讲,x86只要有mov这一条指令就可以完成几乎所有功能了(可能还需要jmp),其他指令都是“多余的”。受此启发,有个大牛做了一个虚拟机加密编译器。它是一个修改版的LCC编译器,输入是C语言代码,输出的obj里面直接包含了虚拟机加密后的代码。如它的名字,函数的所有代码只有mov指令,没有其他任何指令。对,完全没有,连call,jz,ret之类的都没有。
开源项目地址:https://github.com/xoreaxeaxeax/movfuscator
M/o/Vfuscator(简称“o”,听起来像“mobfuscator”)将程序编译成“mov”指令,并且只编译“mov”指令。算术、比较、跳转、函数调用,以及程序需要的一切,都是通过mov操作完成的;没有自修改代码,没有传输触发的计算,也没有其他形式的非 mov 作弊。
继续直接分析原程序:
这类movfuscator 混淆后的程序,MOV混淆是不会混淆函数的逻辑的,因此函数的逻辑还是不变的。大多都是通过逐个比较输入后的字符串的每个字符的方式,比较结果不对就输出“Wrong Flag!”,所以在程序当中就会出现单个的字符,例如:
.text:080493DB C7 05 68 20 06 08 41 00 00 00 mov R2, 41h ; 'A'
movfuscator 混淆后的程序都是通过R2寄存器来存储常量字符,
方法一:搜索字节序列
直接在IDA中搜索字节序列:字符串C7 05 68 20 06 08(“mov R2,”对应字节码)
得到程序中所有使用的常量字符:
连起来就是程序的flag:ALEXCTF{M0Vfusc4t0r_w0rk5_l1ke_m4g1c}
输入到程序验证:
Well Done,这就是正确的flag。
方法二:IDC脚本
也可以用IDA中的IDC脚本和Python脚本来提取代码段中的常量字符:
#include<idc.idc>
static isAscii(p) //判断符合条件的字符
{
if(Byte(p)<='9' && Byte(p)>='0')
return 1;
if(Byte(p)<='z' && Byte(p)>='a')
return 1;
if(Byte(p)<='Z' && Byte(p)>='A')
return 1;
if(Byte(p)=='}' || Byte(p)=='{' || Byte(p)=='_' || Byte(p)=='@' || Byte(p)=='!' || Byte(p)=='#' || Byte(p)=='&' || Byte(p)=='*')
return 1;
return 0;
}
static main()
{
auto start=0x0804829C,end=0x08060B32; //代码段起止地址
auto point=start;
auto str="";
while(point<=end)
{
if(isAscii(point) && Byte(point+1)==0 && Byte(point+2)==0 && Byte(point+3)==0)
{ //汇编中立即数一般都是DWORD
Message("%X %c\\n",point,Byte(point));
str=str+Byte(point);
}
point=point+1;
}
Message("%s\\n",str); //可能是flag
}
运行结果:
得到flag:ALEXCTF{M0Vfusc4t0r_w0rk5_l1ke_m4g1c}
方法三:Python脚本:
start=0x0804829C
end=0x08060B32
flag = ""
while start<end:
if (Byte(start) <= ord('9') and Byte(start)>=ord('0')) or (Byte(start)<=ord('z') and Byte(start)>=ord('a')) or (Byte(start)<=ord('Z') and Byte(start)>=ord('A')) or (Byte(start) == ord('}')) or (Byte(start) == ord('{')) or (Byte(start) == ord('_')) or (Byte(start) == ord('@')) or (Byte(start) == ord('!')) or (Byte(start) == ord('#')) or (Byte(start) == ord('&')) or (Byte(start) == ord('*')):
if Byte(start) and (Byte(start+1)==0) and (Byte(start+2)==0) and (Byte(start+3)==0):
print(chr(Byte(start)))
flag += chr(Byte(start))
start += 1
print(flag)
运行结果:
脚本找到的运行结果flag中都出现了字符2,这是因为脚本在判断的时候的逻辑是:从代码段.text起止地址0x0804829C到0x08060B32,只要字符的ASCII值在数字、大小写字母和几个特殊字符中,即可认为是flag中的一个字符,所以这中判断逻辑是可能出现误判的:
得到flag:ALEXCTF{M0Vfusc4t0r_w0rk5_l1ke_m4g1c}
方法四:bgrep工具
我们从前面的IDA中知道.text:080493DB上的字节序列:字符串C7 05 68 20 06 08(“mov R2,”对应字节码),表明标志的字符是硬编码在二进制文件中的:
bgrep工具:
用法:
bgrep [-B 字节] [-A 字节] [-C 字节] [
-B:bytes_before
-A:bytes_after
-C:bytes_before 和 bytes_after
先安装:
bgrep "C70568200608" ./57move
查找程序当中字节序列:C70568200608
得到的是所有出现的字节序列C70568200608的文件偏移地址,之后+6是字节序列C70568200608的长度是6,再从当前的文件读取指针位置读取一个字节的字符,拼接起来所有的字符就是flag。
Python脚本:
#!/usr/bin/env python2
offsets = [0x000013db, 0x00001dde, 0x000027e1, 0x000031e4, 0x00003b9c, 0x0000459f, 0x00004fa2, 0x000059a5, 0x00006357, 0x00006d5a, 0x0000775d, 0x00008160, 0x00008b0c, 0x0000950f, 0x00009f12, 0x0000a915, 0x0000b2bb, 0x0000bcbe, 0x0000c6c1, 0x0000d0c4, 0x0000da64, 0x0000e467, 0x0000ee6a, 0x0000f86d, 0x00010207, 0x00010c0a, 0x0001160d, 0x00012010, 0x000129a4, 0x000133a7, 0x00013daa, 0x000147ad, 0x0001513b, 0x00015b3e, 0x00016541, 0x00016f44, 0x000178cc]
with open('./57move') as f:
flag = ''
for offset in offsets:
# "mov R2, 41h" is "C70568200608"+"41000000" (the immediate starts after the 6th byte)
# 移动文件读取指针到指定位置
f.seek(offset + 0x6)
#从当前的文件读取指针位置读取一个字节的字符,+6是字节序列C70568200608的长度是6
flag += f.read(1)
print flag
运行结果:
得到flag:ALEXCTF{M0Vfusc4t0r_w0rk5_l1ke_m4g1c}
以上是关于XCTF-攻防世界CTF平台-Reverse逆向类——57re5-packed-movement的主要内容,如果未能解决你的问题,请参考以下文章
XCTF-攻防世界CTF平台-Reverse逆向类——53easyCpp
XCTF-攻防世界CTF平台-Reverse逆向类——65reverse-box
XCTF-攻防世界CTF平台-Reverse逆向类——59mfc逆向-200
XCTF-攻防世界CTF平台-Reverse逆向类——52handcrafted-pyc