问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
某免杀工具后门分析
渗透测试
某免杀工具后门分析 ========= 最近网上看到某免杀exe生成工具存在后门 找到样本来学习一下看看 样本地址: <https://s.threatbook.com/report/file/a737860a66bcd9228cc18de7a51cc736e1a834a13e26cd6f19e2d162fdfef9bd> 0x01 文件信息 --------- 下载好后有2个文件 LoaderMaker.exe 这是用来生成免杀文件的,后门在该文件中 ShellcodeLoader.exe 这是一个模板 这次不学习这东西怎么免杀的 就是看看后门是藏在哪里的 0x02 文件分析 --------- 先看一下LoaderMaker.exe的导出函数有哪些 ![1.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-a72e7e53cc5f1ebdb441d6c4d2da7368365e4178.png) 看到这个函数就感觉有点问题了 这是用来列进程的函数,一个免杀工具好端端的为啥要去列进程 参考了一下大佬的文章,是逆着推的,后面慢慢说 0x03 废话来喽 --------- 首先找到主函数 运行文件后会打印title ![2.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-adf0fd950a68e987c9031491447035a03f7ff55d.png) 主函数位置为sub\_004019A0 ![3.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-d58deefcf7f43f533af33a54dddd7d0a5f7e32d9.png) 打印下面还有2个函数 ### sub\_4011E0 网上说是用来反沙箱的,找了半天找不到特别有用的信息,好像是一个处理字符串的函数 ![4.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-d386b4c83224a924f7ed1561c6b8fb5f8aedf5bb.png) 可以看到从ntdll里面找PfxInitialize函数,然后对比输出结果是否为0x200 去dbg里面跟了一下 ![5.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-ede33f2fb783118631d58c831688656c9b6e61e4.png) 发出了疑惑的声音,这不是在硬编码中写死的吗 后来又去ReactOS看了下 ![6.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-0289b1e4579036fa4a755aede0022d1ad62e13bf.png) 可以看到函数内部执行了UNIMPLEMENTED,再过去看看 ![7.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-80d675962e79056d76063210e2b0148925cc5d81.png) 可以看到是个宏定义,如果满足上面的条件则调用Dbgprint,反之为空 Dbgprint是内核的打印函数,可以不用去管 这里简单的猜测一下,PfxInitialize的返回值应该是在编译ntdll的时候决定的 返回值和CPU架构有关,勉强可以说是反沙箱的函数,只是不是动态确定的就是了 上面是一些简单的猜测,如果有问题欢迎大佬指出 ### sub\_401620 这函数就是用来直接提权的,里面不细究了之前的文章有写过,开启debug特权,开不起就算了 所以你一个免杀工具为啥要debug特权??? 后面的就是混淆shellcode的一些东西了,这脚本的免杀怎么实现的就不在这里说了 毕竟这文章主要是来看后门的 0x04 后门代码分析 ----------- 这里跟着大佬的脚步逆着推 ### sub\_401560 先找到调用CreateToolhelp32Snapshot的函数 sub\_401560 ![8.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-335673e9e731d8406ff6462b1d3d6d39bd81243c.png) 毫不掩饰的遍历进程,通过进程名找到PID再用a1传回去 ### sub\_401710 再往上找到sub\_401710,这里函数太长了截图不完 ![9.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-6ebd21b093b49423adc7e8f356d513d10625a0de.png) 可以看到sub\_401560执行完后如果找到PID就会去执行sub\_401290 再看下面的函数之前先去看看到底找了什么进程吧 看上图有一堆不知道什么的变量,还有循环 到这里看伪代码就会有点不清楚了,可以选择直接去看汇编 ```asm .text:00401710 var_54 = dword ptr -54h .text:00401710 var_50 = dword ptr -50h .text:00401710 var_4C = dword ptr -4Ch .text:00401710 var_48 = dword ptr -48h .text:00401710 var_44 = dword ptr -44h .text:00401710 var_40 = dword ptr -40h .text:00401710 var_3C = dword ptr -3Ch .text:00401710 var_38 = dword ptr -38h .text:00401710 var_34 = dword ptr -34h .text:00401710 var_30 = dword ptr -30h .text:00401710 var_2C = dword ptr -2Ch .text:00401710 var_28 = dword ptr -28h .text:00401710 String2 = word ptr -24h .text:00401710 var_20 = dword ptr -20h .text:00401710 var_1C = dword ptr -1Ch .text:00401710 var_18 = dword ptr -18h .text:00401710 var_14 = dword ptr -14h .text:00401710 var_10 = dword ptr -10h .text:00401710 var_C = word ptr -0Ch .text:00401710 dwProcessId = dword ptr -8 .text:00401710 var_4 = dword ptr -4 .text:00401799 mov edx, [ebp+var_4] .text:0040179C mov eax, [ebp+edx*4+var_54] .text:004017A0 movsx cx, byte_41ADC4[eax] .text:004017A8 mov edx, [ebp+var_4] .text:004017AB mov [ebp+edx*2+String2], cx .text:004017B0 mov eax, [ebp+var_4] .text:004017B3 add eax, 1 .text:004017B6 mov [ebp+var_4], eax .text:004017B9 cmp [ebp+var_4], 0Ch .text:004017BD jnz short loc_4017D2 ``` 上面这些都是参数在栈中对应的位置,稍微把参数对应的位置改一下 先贴一张后面要用到的 ![10.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-1b512e9be562096ada8a8472225559f0bdace064.png) 这里能看到byte\_41ADC4对应的字符串 shellcodeLoader.exe ```asm .text:00401799 mov edx, [ebp-4] ;取出ebp-4的位置存入edx 该位置是用来存放循环次数的 .text:0040179C mov eax, [ebp+edx*4-54] ;将ebp+edx*4-54的位置存入eax 该位置是存放需要取的字符串的位置 .text:004017A0 movsx cx, byte_41ADC4[eax] ;取出byte_41ADC4对应位置的字符 .text:004017A8 mov edx, [ebp-4] ;取出ebp-4的位置存入edx .text:004017AB mov [ebp+edx*2-24], cx ;将得到的字符存入ebp+edx*2-24 .text:004017B0 mov eax, [ebp-4] ;取出循环次数存入eax .text:004017B3 add eax, 1 ;eax+1 .text:004017B6 mov [ebp-4], eax ;加过的循环次数再次存入ebp-4 .text:004017B9 cmp [ebp-4], 0Ch ;判断有无循环到0xC次 .text:004017BD jnz short loc_4017D ;如果已经循环到0xC次跳出循环 ``` 这么看了之后就很明了了 上面v1-v12的变量去byte\_41ADC4找到对应位置的字符就可以了 其实这里动态调试可以马上看到 ![11.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-5ddb5bc32d416c50c3503f282fe885de92f4f810.png) 这里看着还有点不对 再往下看看ida中还有这句 LOWORD(v14) = 112; ![12.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-e2cb7457fbd90bc87e638d2bab34309f6df1d230.png) 这里就明确了找的是资源管理器的PID 虽然动态可以直接看到不过有些程序不能调试,所以静态也是必要的技能 好了可以接着看下面的函数了 ### sub\_401290 去找了某dll的句柄 ![13.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-664f821b034a0c54e120532448a1a5d6ec2c0f0c.png) 这里取字符串的方式和上面的一样,不过取的位置在byte\_41AE20 ![14.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-c873a387337dea3f79e7e8d7d9b1ea5cbb351a09.png) byte\_41AE20=\[A-Za-z\] 这里取出的来的字符串为Kernel 加上v23 = 0x320033; 完整的字符串就是Kernel32 得到Kernel32的句柄 然后用OpenProcess得到资源管理器的句柄 然后使用GetProcAddress得到需要调用的函数地址 ![15.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-73d4a17acfa5a80871185b3985b1d57d03b65cca.png) 这里有些区别 先提取出dword\_41A9E4的数字然后再从byte\_41AE20找到指定字符 ![16.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-6e8e7e57d563e3ec81a8e3173a9e85d39d4c2f17.png) 这里提取出来的函数是VirtullAllocEx 下面还有GetProcAddress ![17.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-6b8aafef44c079bdc4bd398d6f1d8fa0345acd52.png) 和上面的一样 ![18.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-58f6cdacdcff00a4e49cb3d39516ac236e9612e7.png) 这里的函数是WriteProcessMemory 先判断系统的位数,如果是64位则注入shellcode,反之就不动 然后开一块堆内存用来解密shellcode ![19.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-e2b75b5312afd72bbc3be2bf5927b27c3ac9676d.png) 关于解密shellcode这块可以写脚本解密,这次偷懒就直接用x64dbg运行了 ![20.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-f94d6f31a4e82e2f8335c121d83daf472c700d26.png) 解密了之后可以看到这就是一个普通cs的shellcode,甚至无混淆,直接可以看到域名和端口 端口: 0x827=2087 不过看到FC48就可以知道这是一段x64位的shellcode,不过这个后门程序是32位的该怎么去动64位的程序的还需要看下去 ![21.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-c65c3088b2af712218be11e602a741a44a0fc19a.png) 后面的代码调用了前面提取出来的函数 就是在explorer.exe开内存然后把shellcode写入explorer.exe的内存中 调用sub\_401230开一块内存将sub\_41A8B0数据段内的数据复制进去 ![22.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-91327dc3bba077bc974ce2e2e446e66e89e127e0.png) 然后执行这段内存 下面看看这段内存是啥用的 0x05 天堂之门 --------- 这项技术早有耳闻 以前一直没有研究,没想到在这里碰到了 下面简单说一下这技术,这次先不深入学习了以后再专门的文章 该技术可以在32位的进程里面执行64位的汇编指令 其实32位程序会载入32位和64位的ntdll.dll,可以用ProcessHacker看到 ![23.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-5df1220aecc5c040624211369072dc08ab1d26a7.png) 由64位的ntdll模拟一个环境让32位的程序可以正常执行 用来区别执行什么位数的指令用的是段寄存器cs 如果cs为0x23则指令为32位,为0x33则为64位 在ida找到数据段按C可以转为汇编代码 ![24.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-7c1c851444ab4cf343291cdfa7497fc35b1da472.png) 可以看到call了sub\_41A933函数 ![25.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-9aa2d9de5e567d876abff60397968fcb0b5242be.png) sub\_41A933函数push 0x33和eax,这里eax的是call sub\_41A933的下一行指令 不过这已经不重要了,因为IDA和dbg都看不清了,到这里已经转成64位的指令了 这里可以用PE-bear简单的查看一下 ![26.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-d1b00ffaf7f597d40a5f2655c8df8b5fa93739c7.png) 可以把机器码转为不同位数的指令 ![27.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-8c7ef26a11ac89f7a128d5319634e5f3c15eb4e9.png) 前面说了rerf指针会回到call sub\_41A933的下一行指令,就是这位置 不要在意上面的指令为啥不是call,因为这里位数已经改变了 看一下下面的汇编0x60,0x18,这种就是在找PEB里面的dll链表了 因为之前文章有说过这里就不展开了 这块指令就是用来找64位ntdll的地址,然后找里面的某个函数调用 这里可以把机器码全部复制下来然后用x64dbg调试 ```c++ #include <stdio.h> #include <Windows.h> int main() { char sc[] = "\x53\x5B\x85\xC0\x74\x67\x48\x89\xE6\x48\x83\xE4\xF0\x48\x83\xEC\x68\xB8\xFA\x80\x39\x5E\x53\x5B\xE8\x86\x00\x00\x00\x48\x89\xC3\x4D\x31\xC0\x48\x31\xC0\x48\x89\x44\x24\x50\x53\x5B\x48\x89\x44\x24\x48\x48\x89\x44\x24\x40\x48\x89\x44\x24\x38\x53\x5B\x48\x89\x44\x24\x30\x8B\x46\x24\x48\x89\x44\x24\x28\x8B\x46\x20\x48\x89\x44\x24\x20\x53\x5B\x44\x8B\x4E\x14\xBA\x00\x00\x00\x10\x8B\x4E\x30\x53\x5B\xFF\xD3\x48\x89\xF4\xE8\x1C\x00\x00\x00\x5D\x5F\x5E\x5B\xC3\x31\xC0\x48\xF7\xD8\xC3\xE8\xF5\xFF\xFF\xFF\x74\x07\x58\x6A\x33\x53\x5B\x50\xCB\xC3\x53\x5B\xE8\xE4\xFF\xFF\xFF\x53\x5B\x75\x10\x58\x83\xEC\x08\x89\x04\x24\xC7\x44\x24\x04\x23\x00\x00\x00\xCB\xC3\x56\x57\x53\x51\x49\x89\xC0\x6A\x60\x5E\x65\x48\x8B\x06\x48\x8B\x40\x18\x53\x5B\x4C\x8B\x50\x30\x53\x5B\x49\x8B\x6A\x10\x48\x85\xED\x89\xE8\x74\x59\x4D\x8B\x12\x8B\x45\x3C\x83\xC0\x10\x8B\x44\x05\x78\x53\x5B\x48\x8D\x74\x05\x18\xAD\x91\x67\xE3\xDC\xAD\x4C\x8D\x5C\x05\x00\x53\x5B\xAD\x48\x8D\x7C\x05\x00\xAD\x48\x8D\x5C\x05\x00\x53\x5B\x8B\x74\x8F\xFC\x48\x01\xEE\x31\xC0\x99\xAC\x01\xC2\xC1\xC2\x05\x53\x5B\xFF\xC8\x79\xF4\x44\x39\xC2\xE0\xE5\x75\xAC\x0F\xB7\x14\x4B\x53\x5B\x41\x8B\x04\x93\x48\x01\xE8\x59\x5B\x5F\x5E\xC3"; void* exec = VirtualAlloc(0, sizeof sc, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(exec, sc, sizeof sc); ((void(*)())exec)(); return 0; ``` 这段代码找函数的方法和cs类似输入一个特征然后去遍历字符串这样的 ![28.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-2a2bff568f37957eee04bfd5bf6c3c126b8915fb.png) 0x5E3980FA这就是特征,找到的函数为ZwCreateThreadEx 这就是该段代码的作用。,找到64位的ZwCreateThreadEx执行之前写入explorer.exe的shellcode 至于参数是从栈里面传过来的,因为实在不好调试所以就不调了 总结一下就是 找到explorer.exe的pid->开辟内存->写入x64的shellcode->找到x64的ZwCreateThreadEx函数执行shellcdoe 最后的问题就是这个后门是在哪里触发的 找到是谁调用了sub\_401710 ![29.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-7127a329098a0f3f4dfac5eebb9cc25b6855c557.png) 这里有个计数器dword\_41B870 如果等于6就触发后门,不等于就自加 再往上找,因为很多就不截图了直接列一下函数调用顺序 sub\_401950(打印字符串的函数)->sub\_401930->sub\_401910->sub\_4018F0->sub\_4018D0->sub\_4018B0->sub\_401890->sub\_401870->sub\_401850->sub\_401830->sub\_401800 不要看有这么一串调用栈,其实这些函数里面基本就是类似的,如下 ```c++ int __cdecl sub_401930(int a1) { sub_401910(a1); return a1; } ``` 就直接调用 有可能和编译器有关系 最后会发现这是用来打印的函数 ![30.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-24d22c367aa24ea8c4ee0dd59c00277d0a8c387a.png) 上面打印了5次 如果参数不够在if的代码块里置零,这样后面的四次打印就不会触发后门 参数正确的话会在最后打印output时候触发后门 ![31.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-65428704c55ef3441390b2021c2808221b842435.png) 意思就是在如果不生成就不会被上线 生成了就上线 番外 -- 为了确认文章的准确性特意去调了一下那段shellcode,发现了有意思的东西\* **如果下载到的样本是未被修改的话** 这段shellcode无法上线 在调试的时候发现InternetOpenA需要调用的参数全是空 ![32.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-dda8f25276bdd84a7149a41853729d2c84dd96f9.png) 说明shellcode到这里就崩溃了 去附参数的位置看看发现已经全部都置零了 ![33.png](https://shs3.b.qianxin.com/attack_forum/2022/10/attach-76599ad810c58adecd73f052fa8589fa6e25126f.png) 找了文章发现提取出来的shellcode是一样的 去看了一下沙箱的信息,虽然说提取到了恶意的url不过好像也无可疑的http请求 再去看了一下聊天记录的截图好像连接的也不是提取到的地址 所以可能这东西真的不能上线..只是作者逗着玩的 0x06 参考文章 --------- <https://citrusice.github.io/posts/shellcode-loader-backdoor-analysis/>
发表于 2022-10-31 09:30:00
阅读 ( 6901 )
分类:
安全开发
1 推荐
收藏
0 条评论
请先
登录
后评论
Macchiato
13 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!