HDCTF2023 - Reverse方向全WP
文章目录
- [HDCTF 2023]easy_re
- [HDCTF 2023]easy_asm
- [HDCTF 2023]fake_game
- [HDCTF 2023]enc
- [HDCTF 2023]double_code
- [HDCTF 2023]买了些什么呢
- [HDCTF2023]basketball
[HDCTF 2023]easy_re
UPX壳,脱壳
一个base64编码。
[HDCTF 2023]easy_asm
ida打开后可以看到xor 10,al寄存器的内容不知道
WinHex打开,就能看到异或字符串了。
EXP:
enc = b'XTSDVkZecdOqOu#ciOqC}m'
flag = []
for i in range(len(enc)):
flag.append(chr(enc[i]^0x10))
print("".join(flag))
# HDCTF{Just_a_e3sy_aSm}
[HDCTF 2023]fake_game
Pyinstaller编译的,用pyinstxtractor
将game.pyc反编译成py文件
找到对flag进行操作的俩个地方。
先用Z3求出xorr的值,然后再与flag异或得到真正的flag
EXP:
from z3 import *
xorr = [BitVec("num[%d]" % i, 32) for i in range(4)]
s = Solver()
s.add(xorr[0] * 256 - xorr[1] / 2 + xorr[2] * 23 + xorr[3] / 2 == 47118166)
s.add(xorr[0] * 252 - xorr[1] * 366 + xorr[2] * 23 + xorr[3] / 2 - 1987 == 46309775)
s.add(xorr[0] * 6 - xorr[1] * 88 + xorr[2] / 2 + xorr[3] / 2 - 11444 == 1069997)
s.add((xorr[0] - 652) * 2 - xorr[1] * 366 + xorr[2] * 233 + xorr[3] / 2 - 13333 == 13509025)
print(s.check())
for i in xorr:
print(s.model()[i].as_long(), end=",")
# 178940,248,56890,2361
enc =[0x2bab4,0xbc,0xde79,0x96d,0x2baba,0x83,0xde7d,0x909,0x2bab3,0x9c,0xde65,0x949,0x2ba90,0xca,0xde43,0x90a,0x2ba8e,0xa7,0xde5c,0x909,0x2ba8e,0xa7,0xde6a,0x94f,0x2ba86,0xd9,0xde1b,0x944]
xorr=[178940,248,56890,2361]
flag = []
for i in range(len(enc)):
flag.append(chr(enc[i] ^ xorr[i%4]))
print(''.join(flag))
# HDCTF{G0Od_pl2y3r_f0r_Pvz!!}
[HDCTF 2023]enc
sub_411523用了一个TEA加密
v9 就是 key,v7和v8是密文。
写个脚本逆向一下
#include <stdio.h>
#include <stdint.h> // 使用uint32_t数据类型需要包含此头文件
#include <string.h>
#include<iostream>
using namespace std;
// 定义加密函数
void tea_decrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; // 根据TEA算法,解密轮次的计算需要初始化sum
uint32_t delta = 0x9e3779b9;
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
int main() {
uint32_t enc[2]={0x60FCDEF7,0x236DBEC};
uint32_t key[]={0x12,0x34,0x56,0x78};
tea_decrypt(enc,key);
cout<<enc[0];
return 0;
}
得到 3
接着往下看,
不像是花指令,那应该就是SMC了,本来想用动调的,但这里加了反调试,不知道怎么去除,结合前面得到的key,找修改的地方。
最后找到,异或等于a3,可以知道a3 就是前面求出来的 3
写个idapython
for i in range(0x0041D000,0x0041E600):
patch_byte(i,get_wide_byte(i)^3)
print('done')
之后,选中有用的数据U未定义一下,再P创建函数,F5反编译,得到。
这里是一个RC4加密
EXP:
def rc4_decrypt(ciphertext, key):
# 初始化 S-box
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# 初始化变量
i = j = 0
plaintext = []
# 解密过程
for byte in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
plaintext.append(byte ^ k)
return bytes(plaintext)
# 示例用法
encrypted_data = [0xF,0x94,0xAE,0xF2,0xC0,0x57,0xC2,0xE0,0x9A,0x45,0x37,0x50,0xF5,0xA0,0x5E,0xCB,0x2C,0x16,0x28,0x29,0xFE,0xFF,0x33,0x46,0xE,0x57,0x82,0x22,0x52,0x26,0x2B,0x6E,0xE4,0x82,0x24]
# 替换成你的密文
encryption_key = b'you_are_master' # 替换成你的密钥
decrypted_data = rc4_decrypt(encrypted_data, encryption_key)
print("Decrypted Data:", decrypted_data.decode('utf-8'))
# Decrypted Data: HDCTF{y0u_ar3_rc4_t3a_smc_m4ster!!}
[HDCTF 2023]double_code
打开来,慢慢看,start进去,一直进
找到一个Code
alloc:%p\n 在这里 接着进去,找到指向这里的指针。
找到了,根据output写个EXP:
enc = [0x48,0x67,0x45,0x51,0x42,0x7b,0x70,0x6a,0x30,0x68,0x6c,0x60,0x32,0x61,0x61,0x5f,0x42,0x70,0x61,0x5b,0x30,0x53,0x65,0x6c,0x60,0x65,0x7c,0x63,0x69,0x2d,0x5f,0x46,0x35,0x70,0x75,0x7d]
flag = []
for i in range(len(enc)):
x = i % 5
match x:
case 0:
flag.append(chr(enc[i]))
case 1:
flag.append(chr(enc[i]^0x23))
case 2:
flag.append(chr(enc[i]-2))
case 3:
flag.append(chr(enc[i]+3))
case 4:
flag.append(chr(enc[i]+4))
case 5:
flag.append(chr(enc[i]+25))
print("".join(flag))
# HDCTF{Sh3llC0de_and_0pcode_al1_e3sy}
[HDCTF 2023]买了些什么呢
题目运行起来,
一个01背包问题,动态规划,写个EXP解决。
def knapsack(weights, values, capacity):
n = len(weights)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for w in range(capacity + 1):
if weights[i - 1] <= w:
dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1])
else:
dp[i][w] = dp[i - 1][w]
selected_items = []
i, w = n, capacity
while i > 0 and w > 0:
if dp[i][w] != dp[i - 1][w]:
selected_items.append(i-1)
w -= weights[i - 1]
i -= 1
return dp[n][capacity], selected_items
# 商品信息
weights = [2, 5, 10, 9, 3, 6, 2, 2, 6, 8, 2, 3, 3, 2, 9, 8, 2, 10, 8, 6, 4, 3, 4, 2, 4, 8, 3, 8, 4, 10, 7, 1, 9, 1, 5, 7, 1, 1, 7, 4]
values = [8, 1, 5, 9, 5, 6, 8, 2, 3, 7, 5, 4, 3, 7, 6, 7, 9, 3, 10, 5, 2, 4, 5, 2, 9, 5, 8, 10, 2, 9, 6, 3, 7, 3, 9, 6, 10, 1, 2, 9]
# 背包容量
capacity = 50
max_value, selected_items = knapsack(weights, values, capacity)
print("最大价值:", max_value)
print("选择的商品编号:", selected_items)
selected_items = selected_items[::-1]
for i in range(len(selected_items)):
print(selected_items[i],end=' ')
# 最大价值: 116
# 选择的商品编号: [39, 36, 34, 33, 31, 26, 24, 22, 21, 18, 16, 13, 11, 10, 6, 4, 0]
# 0 4 6 10 11 13 16 18 21 22 24 26 31 33 34 36 39
[HDCTF2023]basketball
俩处加密,第一处对一句话进行一个f(x,y)的加密,这里加密用到了俩个伪随机数。加密后的密文是Str2
写一个爆破脚本枚举一下
def f(k1_0, k2_0):
for i in range(len(str)):
k1_0 = (str[i] + k1_0) % 300
k2_0 = (str[i] + k2_0) % 300
str[i] ^= text_66(k1_0, k2_0)
def text_66(a, b):
aa = a
ba = b
if a < b:
aa, ba = ba, aa
if ba:
return text_66(ba, aa % ba)
else:
return aa
for x in range(100):
for y in range(100):
str = [0x55, 0x69, 0x68, 0x78, 0x21, 0x68, 0x72, 0x21, 0x60, 0x21,
0x69, 0x62, 0x65, 0x75, 0x21, 0x7C, 0x69, 0x6A, 0x75, 0x21,
0x48, 0x21, 0x69, 0x64, 0x6D, 0x71, 0x2B, 0x78, 0x6E, 0x74,
0x21, 0x68, 0x72, 0x2B, 0x73, 0x64, 0x6C, 0x68, 0x6F, 0x65,
0x21, 0x78, 0x6E, 0x74, 0x21, 0x75, 0x6E, 0x21, 0x62, 0x49,
0x64, 0x62, 0x6A, 0x21, 0x75, 0x69, 0x64, 0x21, 0x60, 0x73,
0x73, 0x60, 0x78, 0x21, 0x60, 0x6F, 0x65, 0x21, 0x75, 0x69,
0x73, 0x64, 0x64, 0x21, 0x6F, 0x74, 0x66, 0x63, 0x64, 0x73,
0x72, 0x21, 0x62, 0x60, 0x6F, 0x21, 0x77, 0x62, 0x64, 0x76,
0x21, 0x60, 0x72, 0x21, 0x60, 0x21, 0x66, 0x73, 0x6E, 0x74,
0x71, 0x00]
f(x, y)
for i in str:
if i < 33 or i > 127:
break
else:
print(''.join(chr(j) for j in str))
得到的结果不是很准确,
在这里插入图片描述
只能大概看出,this is a hint i help you is remind you to check the array and three numbers can view as a group
翻译后大概就是,数组三个为一组?附件有一个array.txt。
附件内
全是300以内的数字,结合 三个为一组,联想到RGB。可以利用python的PTL库来构造一张彩色图像。
from PIL import Image
# 从文件中读取数据
with open('C:\\Users\\Sciurdae\\Downloads\\basketball\\array.txt', 'r') as f:
data = f.read().split() # 假设数据是空格分隔的
# 指定图像的宽度和高度
width = 637
height = 561
# 创建图像对象
image = Image.new("RGB", (width, height))
# 遍历数据并设置像素值
index = 0
for y in range(height):
for x in range(width):
r, g, b = int(data[index]), int(data[index + 1]), int(data[index + 2])
image.putpixel((x, y), (r, g, b))
index += 3
# 保存图像
image.save('output_image.png')
# 展示图像
image.show()
这一题看了官方的wp,根据hint?
没有在程序中找到o(╥﹏╥)o。只能暂时放一边了。
得到一张写着,我想打篮球的图片。翻译成英语,“I want to play basketball”
再结合flag 为 28 位,可以得到,“I want to play basketballI w”
之后再与code异或就好了。
code = [1,100,52,53,40,15,4,69,46,109,47,40,55,55,92,94,62,70,23,72,8,82,29,65,16,117,117,10]
str = 'I want to play basketballI w'
flag = ''
for i in range(28):
flag += chr(ord(str[i]) ^ code[i])
print(flag)
#HDCTF{$1AM_DVN|<_5|-|0|-|<U}
.(img-x58Np97x-1700493600487)]
得到一张写着,我想打篮球的图片。翻译成英语,“I want to play basketball”
再结合flag 为 28 位,可以得到,“I want to play basketballI w”
之后再与code异或就好了。
code = [1,100,52,53,40,15,4,69,46,109,47,40,55,55,92,94,62,70,23,72,8,82,29,65,16,117,117,10]
str = 'I want to play basketballI w'
flag = ''
for i in range(28):
flag += chr(ord(str[i]) ^ code[i])
print(flag)
#HDCTF{$1AM_DVN|<_5|-|0|-|<U}