好友
阅读权限40
听众
最后登录1970-1-1
|
本帖最后由 lizhirui 于 2018-10-15 20:51 编辑
本文主要突出解决问题的一个思路——自己写了一个汇编转C语言的程序。昨天我对某个crackme分析,打开之后就看到了以下的代码(这里只摘录一部分):
[Asm] 纯文本查看 复制代码 .text:00000000004005FE mov cs:dword_694140, 9C06AA99h
.text:0000000000400608 mov cs:dword_694144, 0B4B2B03Fh
.text:0000000000400612 mov cs:dword_694148, 0C51F73CFh
.text:000000000040061C mov cs:dword_69414C, 223520F8h
.text:0000000000400626 mov cs:dword_694150, 0C0C53B9h
.text:0000000000400630 mov cs:dword_694154, 0B59C78EAh
.text:000000000040063A mov cs:dword_694158, 0F7DE2D34h
.text:0000000000400644 mov cs:dword_69415C, 0B27EEE2Ch
.text:000000000040064E movzx eax, cs:byte_694117
.text:0000000000400655 add eax, 0Bh
.text:0000000000400658 mov cs:byte_694117, al
.text:000000000040065E movzx eax, cs:byte_694103
.text:0000000000400665 add eax, 1Fh
.text:0000000000400668 mov cs:byte_694103, al
.text:000000000040066E mov edx, cs:dword_694178
.text:0000000000400674 mov eax, cs:dword_69417C
.text:000000000040067A xor eax, edx
.text:000000000040067C mov cs:dword_69417C, eax
.text:0000000000400682 mov edx, cs:dword_69417C
.text:0000000000400688 mov eax, cs:dword_694180
.text:000000000040068E xor eax, edx
.text:0000000000400690 mov cs:dword_694180, eax
.text:0000000000400696 mov edx, cs:dword_694180
.text:000000000040069C mov eax, cs:dword_694184
.text:00000000004006A2 xor eax, edx
.text:00000000004006A4 mov cs:dword_694184, eax
.text:00000000004006AA mov edx, cs:dword_694184
.text:00000000004006B0 mov eax, cs:dword_694188
.text:00000000004006B6 xor eax, edx
.text:00000000004006B8 mov cs:dword_694188, eax
.text:00000000004006BE mov edx, cs:dword_694188
.text:00000000004006C4 mov eax, cs:dword_69418C
.text:00000000004006CA xor eax, edx
.text:00000000004006CC mov cs:dword_69418C, eax
.text:00000000004006D2 mov edx, cs:dword_69418C
.text:00000000004006D8 mov eax, cs:dword_694190
大篇的部分都是这样
因此我试图将其还原成C语言观其全貌:
使用了以下的程序(我简单写了个汇编翻译成C语言的翻译引擎,IDA翻译这一堆会卡死):
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 第六题求解程序
{
class Program
{
enum CODE
{
mov = 0,
movzx,
add,
sub,
xor
}
enum ArgType
{
Register = 0,
Variable,
Imm,
}
enum ArgSize
{
_byte = 0,
_dword,
}
enum Register
{
eax = 0,
edx,
al,
}
struct Arg
{
public ArgType Type;
public ArgSize Size;
public ulong VariableBaseAddr;
public string VariableName;
public ulong Offset;
public ulong Index;
public ulong Number;
public Register Reg;
}
struct Instruction
{
public ulong Addr;
public CODE Code;
public Arg[] Arg;
}
static string FormatLine(string line)
{
var r = new StringBuilder();
for(var i = 0;i < line.Length;i++)
{
if(i == 0 || (line[i - 1] != ' ' && line[i - 1] != ',') || line[i] != ' ')
{
r.Append(line[i]);
}
}
return r.ToString();
}
static Instruction AnalysisInstruction(string line)
{
Instruction code = new Instruction();
var seg = line.Split(' ');
var addr = seg[0].Split(':');
code.Addr = Convert.ToUInt64(addr[1],16);
switch(seg[1])
{
case "mov":
code.Code = CODE.mov;
break;
case "movzx":
code.Code = CODE.movzx;
break;
case "add":
code.Code = CODE.add;
break;
case "sub":
code.Code = CODE.sub;
break;
case "xor":
code.Code = CODE.xor;
break;
default:
throw new Exception("Unknown OpCode \"" + seg[1] + "\"");
}
var args = seg[2].Split(',');
var arglist = new List<Arg>();
foreach(var arg in args)
{
var targ = new Arg();
if(arg.IndexOf('_') > 0)
{
targ.Type = ArgType.Variable;
var argaddr = arg.Split(':');
if(argaddr.Length > 1)
{
argaddr[0] = argaddr[1];
}
var msg = argaddr[0].Split('_');
var curaddr = Convert.ToUInt64(msg[1],16);
if(curaddr < 0x694140)
{
targ.VariableBaseAddr = 0x694100UL;
targ.VariableName = "InputBuf";
}
else
{
targ.VariableBaseAddr = 0x694140UL;
targ.VariableName = "EncodeFlag";
}
targ.Offset = curaddr - targ.VariableBaseAddr;
switch(msg[0])
{
case "byte":
targ.Size = ArgSize._byte;
targ.Index = targ.Offset;
break;
case "dword":
targ.Size = ArgSize._dword;
targ.Index = targ.Offset >> 2;
break;
default:
throw new Exception("Unknown Data Type \"" + msg[0] + "\"");
}
}
else
{
switch(arg)
{
case "eax":
targ.Type = ArgType.Register;
targ.Reg = Register.eax;
break;
case "edx":
targ.Type = ArgType.Register;
targ.Reg = Register.edx;
break;
case "al":
targ.Type = ArgType.Register;
targ.Reg = Register.al;
break;
default:
if(arg[arg.Length - 1] == 'h')
{
targ.Type = ArgType.Imm;
targ.Number = Convert.ToUInt64(arg.Substring(0,arg.Length - 1),16);
}
else
{
try
{
targ.Type = ArgType.Imm;
targ.Number = Convert.ToUInt64(arg,16);
}
catch
{
throw new Exception("Unknown Arg Type \"" + arg + "\"");
}
}
break;
}
}
arglist.Add(targ);
}
code.Arg = arglist.ToArray();
return code;
}
static string GetArgString(Arg arg)
{
switch(arg.Type)
{
case ArgType.Imm:
return arg.Number + "";
case ArgType.Variable:
return arg.VariableName + "[" + arg.Index + "]";
default:
throw new Exception("Error Type!");
}
}
static void Main(string[] args)
{
var file = @"D:\exercise\XXXX\第六题待处理汇编.txt";
var result = new StringBuilder();
Stack<string> resultstack = new Stack<string>();
var lines = File.ReadAllLines(file);
var codes = new List<Instruction>();
var eax = "";
var edx = "";
foreach(var line in lines)
{
var pline = FormatLine(line);
codes.Add(AnalysisInstruction(pline));
}
for(var i = 0;i < codes.Count;i++)
{
var arg1str = "";
switch(codes[i].Arg[1].Type)
{
case ArgType.Variable:
case ArgType.Imm:
arg1str = GetArgString(codes[i].Arg[1]);
break;
case ArgType.Register:
switch(codes[i].Arg[1].Reg)
{
case Register.eax:
arg1str = eax;
break;
case Register.edx:
arg1str = edx;
break;
case Register.al:
arg1str = "(" + eax + ") & 0xFF";
break;
}
break;
}
switch(codes[i].Code)
{
case CODE.mov:
case CODE.movzx:
switch(codes[i].Arg[0].Type)
{
case ArgType.Register:
switch(codes[i].Arg[0].Reg)
{
case Register.eax:
eax = arg1str;
break;
case Register.edx:
edx = arg1str;
break;
default:
throw new Exception("Unknown Arg");
}
break;
case ArgType.Variable:
//Get InputBuf Code Only
if(codes[i].Arg[0].VariableName != "InputBuf")
{
break;
}
result.Append(GetArgString(codes[i].Arg[0]));
result.Append(" = ");
result.Append(arg1str);
result.Append(";\n");
resultstack.Push(GetArgString(codes[i].Arg[0]) + " = " + arg1str + ";\n");
if((codes[i].Arg[0].VariableName == "EncodeFlag" && arg1str.IndexOf("InputBuf") > 0) || (codes[i].Arg[0].VariableName == "InputBuf" && arg1str.IndexOf("EncodeFlag") > 0))
{
throw new Exception("Encode Flag is linked to InputBuf!");
}
break;
default:
throw new Exception("Unknown Arg");
}
break;
case CODE.add:
switch(codes[i].Arg[0].Type)
{
case ArgType.Register:
switch(codes[i].Arg[0].Reg)
{
case Register.eax:
eax = "(" + eax + ") - (" + arg1str + ")";
break;
case Register.edx:
edx = "(" + edx + ") - (" + arg1str + ")";
break;
default:
throw new Exception("Unknown Arg");
}
break;
case ArgType.Variable:
result.Append(GetArgString(codes[i].Arg[0]));
result.Append(" -= ");
result.Append(arg1str);
result.Append(";\n");
if((codes[i].Arg[0].VariableName == "EncodeFlag" && arg1str.IndexOf("InputBuf") > 0) || (codes[i].Arg[0].VariableName == "InputBuf" && arg1str.IndexOf("EncodeFlag") > 0))
{
throw new Exception("Encode Flag is linked to InputBuf!");
}
break;
default:
throw new Exception("Unknown Arg");
}
break;
case CODE.sub:
switch(codes[i].Arg[0].Type)
{
case ArgType.Register:
switch(codes[i].Arg[0].Reg)
{
case Register.eax:
eax = "(" + eax + ") + (" + arg1str + ")";
break;
case Register.edx:
edx = "(" + edx + ") + (" + arg1str + ")";
break;
default:
throw new Exception("Unknown Arg");
}
break;
case ArgType.Variable:
result.Append(GetArgString(codes[i].Arg[0]));
result.Append(" += ");
result.Append(arg1str);
result.Append(";\n");
if((codes[i].Arg[0].VariableName == "EncodeFlag" && arg1str.IndexOf("InputBuf") > 0) || (codes[i].Arg[0].VariableName == "InputBuf" && arg1str.IndexOf("EncodeFlag") > 0))
{
throw new Exception("Encode Flag is linked to InputBuf!");
}
break;
default:
throw new Exception("Unknown Arg");
}
break;
case CODE.xor:
switch(codes[i].Arg[0].Type)
{
case ArgType.Register:
switch(codes[i].Arg[0].Reg)
{
case Register.eax:
eax = "(" + eax + ") ^ (" + arg1str + ")";
break;
case Register.edx:
edx = "(" + edx + ") ^ (" + arg1str + ")";
break;
default:
throw new Exception("Unknown Arg");
}
break;
case ArgType.Variable:
result.Append(GetArgString(codes[i].Arg[0]));
result.Append(" ^= ");
result.Append(arg1str);
result.Append(";\n");
if((codes[i].Arg[0].VariableName == "EncodeFlag" && arg1str.IndexOf("InputBuf") > 0) || (codes[i].Arg[0].VariableName == "InputBuf" && arg1str.IndexOf("EncodeFlag") > 0))
{
throw new Exception("Encode Flag is linked to InputBuf!");
}
break;
default:
throw new Exception("Unknown Arg");
}
break;
}
}
result.Clear();
while(resultstack.Count > 0)
{
result.Append(resultstack.Pop());
}
File.WriteAllText(@"D:\exercise\XXXX\第六题汇编处理结果_InputBuf_Only_Reverse.txt",result.ToString());
}
}
}
该程序证明了一大堆代码中的一个dword数组和另一个输入缓冲数组并没有任何的关联,且一大堆代码之后的代码也没有使用到那个dword的代码,因此上面的代码同时进行了过滤操作,仅仅过滤出了输入缓冲区的操作代码,并且进行了代码反转,输出的是Flag解密代码(源代码是加密输入缓冲区内容然后与已有数据进行比较)
详情文件由于太长都在附件中,crackme(6-WxyVM2)也在,工程代码也都在(VS2017),crackme附带IDA x64的数据库。
求解.rar
(2.22 MB, 下载次数: 47)
|
免费评分
-
查看全部评分
|