Flare-ON 9th 之第八题BackDoor

WriteUp 2年前 (2022) admin
348 0 0

Flare-ON 9th 之第八题BackDoor

本文为看雪论坛精华文章

看雪论坛作者ID:wmsuper




概述


今年由火眼举办的flare-on 9th CTF刚刚结束,接下来准备介绍令我印象比较深刻的第八题BackDoor的解题方法。
Flare-ON 9th 之第八题BackDoor





C#反混淆


混淆原理


使用DnSpy打开exe,确定无疑的是该C#编写的程序肯定经过了混淆,不是已知的任何一种混淆壳,无法使用De4dot直接反混淆:
Flare-ON 9th 之第八题BackDoor


第一层混淆


让我们简单先分析下混淆的原理,根据原理来完成去混淆,通过分析,有大部分函数是通过触发异常来完成解密方法体的调用的,如下所示:
Flare-ON 9th 之第八题BackDoor
flare_71方法使用DynamicMethod根据传入的字节码数组来进行动态调用:
Flare-ON 9th 之第八题BackDoor
这类受保护的方法还有一个很明显的特征就是开头是两个NOP,而且调用了flare_71,知道这些后就可以编写代码还原第一层混淆:
Flare-ON 9th 之第八题BackDoor
代码如下所示,自动寻找符合特征的函数,调用目标exe里面的相关方法并修复exe。

private static void flareon_wrap_decrypt(IList<TypeDef> typeDefs) {      foreach (var typeDef in typeDefs)         foreach (var methodDef in typeDef.Methods)             if (methodDef.Module.Name == Assembly.ManifestModule.ScopeName && methodDef.HasBody &&                 methodDef.Body.Instructions.Count > 2 && methodDef.Body.Instructions[0].OpCode == OpCodes.Nop &&                 methodDef.Body.Instructions[1].OpCode == OpCodes.Nop)             {                 var is_wrap = false;                 var find_true_call = false;                 MethodDef true_call_MethodDef = null;                 var is_get_all_args = false;                 var args_token = new int[2];                 var Instructions = methodDef.Body.Instructions;                   for (var i = 0; i < Instructions.Count; i++)                 {                     if (!find_true_call && Instructions[i].OpCode == OpCodes.Call)                     {                          find_true_call = true;                         true_call_MethodDef = (MethodDef)Instructions[i].Operand;                     }                     if (Instructions[i].OpCode == OpCodes.Ldsfld && Instructions[i + 1].OpCode == OpCodes.Ldsfld)                     {                          args_token[0] = ((FieldDef)Instructions[i].Operand).MDToken.ToInt32();                         args_token[1] = ((FieldDef)Instructions[i + 1].Operand).MDToken.ToInt32();                         Console.WriteLine("---------------------");                         Console.WriteLine(Instructions[i].Operand.ToString());                          Console.WriteLine(Instructions[i + 1].Operand.ToString());                         Console.WriteLine("---------------------");                         is_get_all_args = true;                     }                     if (Instructions[i].OpCode == OpCodes.Call && Instructions[i].Operand.ToString().Contains("flare_71") && is_get_all_args)                     {                           is_wrap = true;                     }                  }                 if (is_wrap && find_true_call)                 {                     CurrentMethod = methodDef;                     var fieldInfo0 = Assembly.Modules.FirstOrDefault().ResolveField(args_token[0]);                     var fieldInfo1 = Assembly.Modules.FirstOrDefault().ResolveField(args_token[1]);                     var arg0 = (Dictionary<uint, int>)fieldInfo0.GetValue(null);                     var arg1 = (byte[])fieldInfo1.GetValue(null);                      Console.WriteLine(methodDef.FullName);                     var dm = flare.flare_71(Assembly.Modules.FirstOrDefault(), true_call_MethodDef.MDToken.ToInt32(), arg0, arg1);                      var methodBody = MethodBodyReader.CreateCilBody(AssemblyWriter.moduleDef, arg1, null, true_call_MethodDef.Parameters, 1, true_call_MethodDef.Body.MaxStack, (uint)(arg1.Length), true_call_MethodDef.Body.LocalVarSigTok, GenericParamContext.Create(true_call_MethodDef));                      true_call_MethodDef.FreeMethodBody();                     true_call_MethodDef.Body = methodBody;                     Console.WriteLine(true_call_MethodDef.Name);                    }              } }


第二层混淆


在解密出第一层混淆,很快又发现了第二层混淆, 通过方法体的token算出hash,然后通过hash索引PE文件中区段数据,经过RC4解密解密出方法体。
Flare-ON 9th 之第八题BackDoor
Flare-ON 9th 之第八题BackDoor
第二层混淆被保护的方法体的名称都是flared打头的:
Flare-ON 9th 之第八题BackDoor
接下来编写程序自动化找到这些函数,并调用RC4解密进行修复,代码如下所示:

private static void flareon_decrypt(IList<TypeDef> typeDefs){     foreach (var typeDef in typeDefs)        foreach (var methodDef in typeDef.Methods)            if (methodDef.Module.Name == Assembly.ManifestModule.ScopeName  &&                  methodDef.ToString().Contains("flared"))            {                Console.WriteLine(methodDef.Name);                var token = methodDef.MDToken.ToInt32();                var method = Assembly.Modules.FirstOrDefault()?.ResolveMethod(token);                var ILcode = method.GetMethodBody().GetILAsByteArray();                var hash_text = flare.flared_66(Assembly.Modules.FirstOrDefault(), token);                byte[] sec_data = GetSectionData(hash_text);                byte[] decrypted_IL_code = flare.rc4(new byte[] { 18, 120, 171, 223 }, sec_data);                var dm = flare.flared_67(Assembly.Modules.FirstOrDefault(), decrypted_IL_code, token);                Console.WriteLine(sec_data.Length);                 var methodBody = MethodBodyReader.CreateCilBody(AssemblyWriter.moduleDef, decrypted_IL_code, null, methodDef.Parameters, 1, methodDef.Body.MaxStack, (uint)(decrypted_IL_code.Length), methodDef.Body.LocalVarSigTok, GenericParamContext.Create(methodDef));                 if(methodDef.Body.HasExceptionHandlers)                {                    Console.WriteLine(methodDef.Name+": " +methodDef.Body.ExceptionHandlers.Count);                }                methodDef.FreeMethodBody();                methodDef.Body = methodBody;            } }


至此,程序反混淆完成,开始分析。





DNS隧道协议


在运行程序后,使用wireshark观察其网络活动,一开始我就注意到dns活动,猜测该后门和C&C交互使用DNS隧道进行通信:
Flare-ON 9th 之第八题BackDoor
编写一个DNS server模拟C&C的响应包并对exe进行调试:

from dnslib import *from dnslib.server import *import sysimport time class TestResolver:    def __init__(self):        self.data=[]        op=[2, 10, 8, 19, 11, 1, 15, 13, 22, 16, 5, 12, 21, 3, 18, 17, 20, 14, 9, 7, 4]        for i in op:            op_str=str(i)            payload_len=len(op_str)            s=['43']            for k in range(payload_len):                s.append(str(ord(op_str[k])))            s=s+(4-len(s))*["0"]            pl='.'.join(s)            self.data+=(['192.0.0.%d'%(payload_len+1)]+[pl])         self.data=100*self.data        print(self.data)        self.pos=0     def resolve(self,request,handler):         reply = request.reply()        qname = request.q.qname        qtype = request.q.qtype         if "flare-on.com" in str(qname) and QTYPE[qtype]=='A':            answer = RR(rname=qname,ttl=60, rdata=A(self.data[self.pos]))            self.pos+=1            reply.add_answer(answer)            return reply        reply.header.rcode = getattr(RCODE,'NXDOMAIN')        return reply  def main():    resolver = TestResolver()    logger = DNSLogger(prefix=False)    dns_server = DNSServer(resolver,port=53, address='0.0.0.0', logger=logger)    dns_server.start_thread()    try:        while True:            time.sleep(600)            sys.stderr.flush()            sys.stdout.flush()    except KeyboardInterrupt:        sys.exit(0)if __name__ == '__main__':    main()


程序中处理数据包的地方如下所示,根据不同的功能码执行不同的cmd:
Flare-ON 9th 之第八题BackDoor
通过动态调试,分析清楚了协议响应包的格式,
[agent_id]+[payload size]+[opcode]+[pad]





解密flag


前面分析了那么多,那么flag究竟在哪呢?Rc4解密函数被调用了2次,一次用于解密方法体,另一次用于解密flag:
Flare-ON 9th 之第八题BackDoor
RC4密钥是在处理数据包的同时,不断对append的数据,最后得到哈希值作为key:
Flare-ON 9th 之第八题BackDoor
只有这些操作全部调用完成,才会触发解密逻辑:
Flare-ON 9th 之第八题BackDoor
加密的数据和方法体一样,也是在区段数据里面,知道这些,就可以直接编写脚本解密出flag了,脚本如下所示:

import hashlibfrom Crypto.Cipher import ARC4def to_ps(c):    return "powershell -exec bypass -enc "" + c + """op_str=[#74fbaf68(19,"146","JChwaW5nIC1uIDEgMTAuNjUuNDUuMyB8IGZpbmRzdHIgL2kgdHRsKSAtZXEgJG51bGw7JChwaW5nIC1uIDEgMTAuNjUuNC41MiB8IGZpbmRzdHIgL2kgdHRsKSAtZXEgJG51bGw7JChwaW5nIC1uIDEgMTAuNjUuMzEuMTU1IHwgZmluZHN0ciAvaSB0dGwpIC1lcSAkbnVsbDskKHBpbmcgLW4gMSBmbGFyZS1vbi5jb20gfCBmaW5kc3RyIC9pIHR0bCkgLWVxICRudWxs"),(18,"939","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4AMgAyAC4ANAAyACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgAxADAALgAyADMALgAyADAAMAAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4ANAA1AC4AMQA5ACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgAxADAALgAxADkALgA1ADAAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA="),(16,"e87","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANQAxAC4AMQAxACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgA2ADUALgA2AC4AMQAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANQAyAC4AMgAwADAAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA7ACQAKABwAGkAbgBnACAALQBuACAAMQAgADEAMAAuADYANQAuADYALgAzACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwA"),(15,"197","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4AMQAwAC4ANAAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4ANQAwAC4AMQAwACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgAxADAALgAyADIALgA1ADAAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA7ACQAKABwAGkAbgBnACAALQBuACAAMQAgADEAMAAuADEAMAAuADQANQAuADEAOQAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsAA=="),(14,"3a7","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4AMgAxAC4AMgAwADEAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA7ACQAKABwAGkAbgBnACAALQBuACAAMQAgADEAMAAuADEAMAAuADEAOQAuADIAMAAxACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgAxADAALgAxADkALgAyADAAMgAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4AMQAwAC4AMgA0AC4AMgAwADAAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA="),(10,"f38","hostname"),(17,"2e4","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANAA1AC4AMQA4ACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgA2ADUALgAyADgALgA0ADEAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA7ACQAKABwAGkAbgBnACAALQBuACAAMQAgADEAMAAuADYANQAuADMANgAuADEAMwAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANQAxAC4AMQAwACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwA"),(13,"e38","bnNsb29rdXAgZmxhcmUtb24uY29tIHwgZmluZHN0ciAvaSBBZGRyZXNzO25zbG9va3VwIHdlYm1haWwuZmxhcmUtb24uY29tIHwgZmluZHN0ciAvaSBBZGRyZXNz"),(12,"570","JAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANAAuADUAMAAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANAAuADUAMQAgAHwAIABmAGkAbgBkAHMAdAByACAALwBpACAAdAB0AGwAKQAgAC0AZQBxACAAJABuAHUAbABsADsAJAAoAHAAaQBuAGcAIAAtAG4AIAAxACAAMQAwAC4ANgA1AC4ANgA1AC4ANgA1ACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwAOwAkACgAcABpAG4AZwAgAC0AbgAgADEAIAAxADAALgA2ADUALgA1ADMALgA1ADMAIAB8ACAAZgBpAG4AZABzAHQAcgAgAC8AaQAgAHQAdABsACkAIAAtAGUAcQAgACQAbgB1AGwAbAA7ACQAKABwAGkAbgBnACAALQBuACAAMQAgADEAMAAuADYANQAuADIAMQAuADIAMAAwACAAfAAgAGYAaQBuAGQAcwB0AHIAIAAvAGkAIAB0AHQAbAApACAALQBlAHEAIAAkAG4AdQBsAGwA"),(11,"818","RwBlAHQALQBOAGUAdABUAEMAUABDAG8AbgBuAGUAYwB0AGkAbwBuACAAfAAgAFcAaABlAHIAZQAtAE8AYgBqAGUAYwB0ACAAewAkAF8ALgBTAHQAYQB0AGUAIAAtAGUAcQAgACIARQBzAHQAYQBiAGwAaQBzAGgAZQBkACIAfQAgAHwAIABTAGUAbABlAGMAdAAtAE8AYgBqAGUAYwB0ACAAIgBMAG8AYwBhAGwAQQBkAGQAcgBlAHMAcwAiACwAIAAiAEwAbwBjAGEAbABQAG8AcgB0ACIALAAgACIAUgBlAG0AbwB0AGUAQQBkAGQAcgBlAHMAcwAiACwAIAAiAFIAZQBtAG8AdABlAFAAbwByAHQAIgA="),(4, "ea5","WwBTAHkAcwB0AGUAbQAuAEUAbgB2AGkAcgBvAG4AbQBlAG4AdABdADoAOgBPAFMAVgBlAHIAcwBpAG8AbgAuAFYAZQByAHMAaQBvAG4AUwB0AHIAaQBuAGcA"),(5, "bfb","net user"),(3, "113","whoami"),(1, "c2e","RwBlAHQALQBOAGUAdABJAFAAQQBkAGQAcgBlAHMAcwAgAC0AQQBkAGQAcgBlAHMAcwBGAGEAbQBpAGwAeQAgAEkAUAB2ADQAIAB8ACAAUwBlAGwAZQBjAHQALQBPAGIAagBlAGMAdAAgAEkAUABBAGQAZAByAGUAcwBzAA=="),(7, "b","RwBlAHQALQBDAGgAaQBsAGQASQB0AGUAbQAgAC0AUABhAHQAaAAgACIAQwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwAiACAAfAAgAFMAZQBsAGUAYwB0AC0ATwBiAGoAZQBjAHQAIABOAGEAbQBlAA=="),(8,"2b7","RwBlAHQALQBDAGgAaQBsAGQASQB0AGUAbQAgAC0AUABhAHQAaAAgACcAQwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwAgACgAeAA4ADYAKQAnACAAfAAgAFMAZQBsAGUAYwB0AC0ATwBiAGoAZQBjAHQAIABOAGEAbQBlAA=="),(9,"9b2","RwBlAHQALQBDAGgAaQBsAGQASQB0AGUAbQAgAC0AUABhAHQAaAAgACcAQwA6ACcAIAB8ACAAUwBlAGwAZQBjAHQALQBPAGIAagBlAGMAdAAgAE4AYQBtAGUA"),(2,"d7d","RwBlAHQALQBOAGUAdABOAGUAaQBnAGgAYgBvAHIAIAAtAEEAZABkAHIAZQBzAHMARgBhAG0AaQBsAHkAIABJAFAAdgA0ACAAfAAgAFMAZQBsAGUAYwB0AC0ATwBiAGoAZQBjAHQAIAAiAEkAUABBAEQARAByAGUAcwBzACIA"),(22,"709","systeminfo | findstr /i "Domain""),(20,"3c9974","RwBlAHQALQBOAGUAdABJAFAAQwBvAG4AZgBpAGcAdQByAGEAdABpAG8AbgAgAHwAIABGAG8AcgBlAGEAYwBoACAASQBQAHYANABEAGUAZgBhAHUAbAB0AEcAYQB0AGUAdwBhAHkAIAB8ACAAUwBlAGwAZQBjAHQALQBPAGIAagBlAGMAdAAgAE4AZQB4AHQASABvAHAA"),(21,"8e6","RwBlAHQALQBEAG4AcwBDAGwAaQBlAG4AdABTAGUAcgB2AGUAcgBBAGQAZAByAGUAcwBzACAALQBBAGQAZAByAGUAcwBzAEYAYQBtAGkAbAB5ACAASQBQAHYANAAgAHwAIABTAGUAbABlAGMAdAAtAE8AYgBqAGUAYwB0ACAAUwBFAFIAVgBFAFIAQQBkAGQAcgBlAHMAcwBlAHMA")]def get_info(key):    no_ps=[10,5,3,22]    for i in op_str:        num=i[0]        if num==key:            s=i[2]            if num not in no_ps:                s=to_ps(s)            return (num,i[1],s) FLARE15_c = [250,242,240,235,243,249,247,245,238,232,253,244,237,251,234,233,236,246,241,255,252]sh='' stack='System.Object InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)System.Object Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)'key_str=''d=[]for i in FLARE15_c:    op=i^ 248    print(op)    d.append(op)    info=get_info(op)    sh+=info[1]    if op!=4:        key_str+=(stack+info[2]) print(sh[::-1][0:8])print(d) hx = hashlib.sha256(key_str.encode('utf8')).digest()cipher = ARC4.new(hx)with open('enc_data.bin', 'rb') as fp:    enc_data = fp.read()dec_data = cipher.decrypt(enc_data)with open('dec_data.bin', 'wb') as fp:    fp.write(dec_data)


得到flag:

Flare-ON 9th 之第八题BackDoor



Flare-ON 9th 之第八题BackDoor


看雪ID:wmsuper

https://bbs.pediy.com/user-home-651413.htm

*本文由看雪论坛 wmsuper 原创,转载请注明来自看雪社区

Flare-ON 9th 之第八题BackDoor



# 往期推荐

1.CVE-2022-21882提权漏洞学习笔记

2.wibu证书 – 初探

3.win10 1909逆向之APIC中断和实验

4.EMET下EAF机制分析以及模拟实现

5.sql注入学习分享

6.V8 Array.prototype.concat函数出现过的issues和他们的POC们


Flare-ON 9th 之第八题BackDoor


Flare-ON 9th 之第八题BackDoor

球分享

Flare-ON 9th 之第八题BackDoor

球点赞

Flare-ON 9th 之第八题BackDoor

球在看


Flare-ON 9th 之第八题BackDoor

点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):Flare-ON 9th 之第八题BackDoor

版权声明:admin 发表于 2022年12月6日 下午6:01。
转载请注明:Flare-ON 9th 之第八题BackDoor | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...