ezVK
涨姿势了...
信息收集 Vulcan && SPIRV-Tools
关键是怎么提取资源
动调跟到这里
一个是起始位置一个是大小 提取出来写入dumpp
import idaapi
# Function to dump memory range to a file
def dump_memory(start_addr, size, file_path):
# Open the file for writing in binary mode
with open(file_path, "wb") as f:
# Iterate over each byte in the range and write it to the file
for i in range(size):
# Read a byte from the current address
byte = idaapi.get_byte(start_addr + i)
# Write the byte to the file
f.write(byte.to_bytes(1, 'little'))
print(f"Dumped memory range from {hex(start_addr)} to {hex(start_addr + size)} into {file_path}")
# Example usage:
# Replace 'start_addr' with the starting address of the memory range you want to dump
# Replace 'size' with the size of the memory range in bytes
# Replace 'output_file_path' with the path to the file where you want to write the memory dump
start_addr = 0x7FF6063AA1D0 # Replace with the actual start address
size = 0xDB4 # Replace with the actual size
output_file_path = "E:\\memory_dump.bin" # Replace with your desired file path
# Call the function to perform the memory dump
dump_memory(start_addr, size, output_file_path)
然后kali安装spirv-cross
得到代码:
#version 450
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
const uint _80[5] = uint[](1214346853u, 558265710u, 559376756u, 1747010677u, 1651008801u);
layout(binding = 0, std430) buffer V
{
uint v[];
} _23;
void main()
{
uint cnt = gl_GlobalInvocationID.x * 2u;
uint sum = 0u;
uint l = _23.v[cnt];
uint r = _23.v[cnt + 1u];
for (int i = 1; i <= 40; i++)
{
l += ((((((~(r << uint(3))) & (r >> uint(5))) | ((r << uint(3)) & (~(r >> uint(5))))) ^ (~r)) & ((r << uint(3)) ^ (r >> uint(5)))) ^ ((~((~(sum + _80[sum & 4u])) | (~((r >> uint(3)) & (r << uint(2)))))) & (l | (~l))));
sum += 1932555628u;
r += ((((((~(l << uint(3))) & (l >> uint(5))) | ((l << uint(3)) & (~(l >> uint(5))))) ^ (~l)) & ((l << uint(3)) ^ (l >> uint(5)))) ^ ((~((~(sum + _80[(sum >> uint(11)) & 4u])) | (~((l >> uint(3)) & (l << uint(2)))))) & (r | (~r))));
}
_23.v[cnt] = l;
_23.v[cnt + 1u] = r;
}
类tea系列 逆向即可
#include<bits/stdc++.h>
#include<stdint.h>
using namespace std;
//#define unsigned int unsigned int
void dec(unsigned int v[2],unsigned int key[]){
unsigned int DELTA = 1932555628u;
unsigned int sum = 40*DELTA;
unsigned int l = v[0],r = v[1];
for (int i = 1; i <= 40; i++)
{
// l += ((((((~(r << unsigned int(3))) & (r >> unsigned int(5))) | ((r << unsigned int(3)) & (~(r >> unsigned int(5))))) ^ (~r)) & ((r << unsigned int(3)) ^ (r >> unsigned int(5)))) ^ ((~((~(sum + _80[sum & 4u])) | (~((r >> unsigned int(3)) & (r << unsigned int(2)))))) & (l | (~l))));
// sum += 1932555628u;
// r += ((((((~(l << unsigned int(3))) & (l >> unsigned int(5))) | ((l << unsigned int(3)) & (~(l >> unsigned int(5))))) ^ (~l)) & ((l << unsigned int(3)) ^ (l >> unsigned int(5)))) ^ ((~((~(sum + _80[(sum >> unsigned int(11)) & 4u])) | (~((l >> unsigned int(3)) & (l << unsigned int(2)))))) & (r | (~r))));
r -= ((((((~(l << (3))) & (l >> (5))) | ((l << (3)) & (~(l >> (5))))) ^ (~l)) & ((l << (3)) ^ (l >> (5)))) ^ ((~((~(sum + key[(sum >> (11)) & 4u])) | (~((l >> (3)) & (l << (2)))))) & (r | (~r))));
sum -= DELTA;
l -= ((((((~(r << (3))) & (r >> (5))) | ((r << (3)) & (~(r >> (5))))) ^ (~r)) & ((r << (3)) ^ (r >> (5)))) ^ ((~((~(sum + key[sum & 4u])) | (~((r >> (3)) & (r << (2)))))) & (l | (~l))));
}
v[0] = l;
v[1] = r;
}
signed main(){
unsigned int key[] = {1214346853u, 558265710u, 559376756u, 1747010677u, 1651008801u};
unsigned int v[] = {0x185B72AF, 0x0631D2C6, 0xDE8B33CC, 0x31EBCD9F, 0x05DB8B33, 0x0A8D77D0, 0x865C6111, 0xBF032335,
0x722228A5, 0xAD833A57, 0xB7C3456F,0} ;
for(int i=0;i<6;i++){
dec((unsigned int*)(v+2*i),key);
}
for(int i=0;i<11;i++)cout<<v[i]<<",";
}
python n2s转一下DubheCTF{Go0Od!!!You_4re_Vu1k@N_Mast3r^^
补上}
发现还差一位 爆破即可...
DubheCTF{Go0Od!!!You_4re_Vu1k@N_Mast3r^^_}
跟Google2017那道moon很相似~ 都使用了着色器代码..
VMT
一堆反调试 IDApatch不干净 直接sharpod过
CFF把dll can move去掉
输入完过后触发了一大堆异常
调着调着密文就出现了
还有N0ThisiS4F4k3K3Y
变化后的密钥
但是这里调不进去? 一直在触发异常....
后面发现可以把x32的db删掉 然后只在这个函数处下断点 重新F9就可以断下了
调试时发现把我们输入的ascii都转成了hex拼接
substr:
一堆datacopy 调了调发现分别取了input的四段
sub_4031B0
跟进去发现其实就是一个按位xor
xor完后注意这里
跟进去
继续跟进
很长的一个函数
注意到结尾处
结合前面的大致能猜到是在生成一个表
x32动调看
熟悉的table google一下
SM4
我们已经知道密文密钥 直接cyberchef一把梭
DubheCTF{VMT_H00K_4ND_$3H_15_U53FUL}
这里不得不%一下Ysiel学长
手撕SM4 orz
Destination
一大堆花指令混淆
两种思路:
- trace打印指令流分析
- patch花指令
trace方法跟着试了试并没有太成功 最后打印出来感觉不全...
DubheCTF2024 Writeup - 星盟安全团队
那就硬patch花指令吧
大致看看影响反编译的花指令
也就是E8 00 00 00 00 83 04 24 05 C3
这串
直接nop即可
但注意到还有这种
nop前面的同时还要
对后面 0F 84
0F 85
这种跳转指令进行处理
以上面图为例 我们把0F 84 48 17 00 00
nop掉
如果是 0F 85
0F 84
就直接nop后jmp 后面不用管
同时也理解了jz jnz机器码的意义
跳转地址采用的是相对PC的寻址0x414350+0x6+0xA2 == 0x414356+0x6+0x9C == 0x4143F8
脚本如下:
from tqdm import *
binfile = open("Destination.exe","rb").read()
founds = []
index = binfile.find(b'\xE8\x00\x00\x00\x00\x83\x04\x24\x05\xC3')
# find all junkcode
while index!=-1:
founds.append(index)
index = binfile.find(b'\xE8\x00\x00\x00\x00\x83\x04\x24\x05\xC3',index+1) #! index+1 ! 不然死循环了...
print(index)
binfile = bytearray(binfile)
print(len(founds))
# replace all matches
for found in founds:
patch = ["nop"]*10 # call $+5 这一段可以全部nop
instr = binfile[found+10:found+12]
# 处理 jnz jz 花指令
if instr == b'\x0F\x84' or instr == b'\x0F\x85':
if instr == b'\x0F\x84':
patch += ["nop"]*6 # 把jnz全部nop
elif instr == b'\x0F\x85':
patch += ["nop","jmp"]+["pass"]*4
next_instr = binfile[found+16:found+18]
if next_instr == b'\x0F\x84' or next_instr == b'\x0F\x85':
if next_instr == b'\x0F\x84':
patch += ["nop"]*6 # 把jnz全部nop
elif next_instr == b'\x0F\x85':
patch += ["nop","jmp"]+["pass"]*4
for i in range(len(patch)): # 替换回机器码
if patch[i] == "nop":
binfile[found+i] = 0x90
elif patch[i] == "jmp":
binfile[found+i] = 0xE9
open("Patched_Destination.exe","wb").write(binfile)
然后在4140D7
处有一堆jmp跳转
一次指令一次jmp...
处理后反编译得到
int sub_4140D7()
{
unsigned int v0; // ecx
unsigned int v3; // [esp+0h] [ebp-10Ch]
unsigned int v4; // [esp+C8h] [ebp-44h]
unsigned int v5; // [esp+D4h] [ebp-38h]
int v6; // [esp+ECh] [ebp-20h]
unsigned int i; // [esp+F8h] [ebp-14h]
int v8; // [esp+104h] [ebp-8h]
v8 = 50;
v4 = 0;
v5 = dword_4234A8[11];
do
{
v4 -= 1531682718;
v6 = (v4 >> 2) & 3;
for ( i = 0; i < 0xB; ++i )
{
v3 = (((v5 ^ dword_42309C[v6 ^ i & 3]) + (dword_4234AC[i] ^ v4)) ^ (((16 * v5) ^ ((unsigned int)dword_4234AC[i] >> 3))
+ ((4 * dword_4234AC[i]) ^ (v5 >> 5))))
+ dword_4234A8[i];
dword_4234A8[i] = v3;
v5 = v3;
}
v0 = (((v5 ^ dword_42309C[v6 ^ i & 3]) + (dword_4234A8[0] ^ v4)) ^ (((16 * v5) ^ ((unsigned int)dword_4234A8[0] >> 3))
+ ((4 * dword_4234A8[0]) ^ (v5 >> 5))))
+ dword_4234A8[11];
dword_4234A8[11] = v0;
v5 = v0;
}
while ( --v8 );
return 1;
}
还有一个sub_413F77
void __usercall sub_413F77(int a1@<eax>, int a2@<ecx>, int a3@<ebp>)
{
int v3; // ecx
int v4; // eax
unsigned int v5; // esi
unsigned int v6; // edi
int v7; // ecx
unsigned int v8; // esi
v3 = a2 + 2;
v4 = a1 - 1;
while ( 1 )
{
--a3;
v5 = 0;
do
{
v6 = v5 >> 31;
v7 = v3 - 3;
if ( v5 >> 31 == 1 )
v8 = (2 * v5) ^ 0x84A6972F;
else
v8 = 2 * v5;
v5 = v8 + 1;
v3 = v7 - 2;
}
while ( v5 != 32 );
dword_4234A8[v6] = 32;
v4 -= 2;
if ( v6 == 11 )
__asm { retf }
}
}
exp直接搬了...
import struct
from ctypes import c_uint32
DELTA = 0xa4b46062
def encrypt(v, n, k):
# rounds = 6 + int(52 / n)
rounds = 50
sum = c_uint32(0)
z = v[n - 1].value
while rounds > 0:
sum.value += DELTA
e = (sum.value >> 2) & 3
p = 0
while p < n - 1:
y = v[p + 1].value
v[p].value += (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
z = v[p].value
p += 1
y = v[0].value
v[n - 1].value += (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
z = v[n - 1].value
rounds -= 1
def decrypt(v, n, k):
rounds = 50
sum = c_uint32(rounds * DELTA)
y = v[0].value
while rounds > 0:
e = (sum.value >> 2) & 3
p = n - 1
while p > 0:
z = v[p - 1].value
v[p].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p ^ e) & 3] ^ z)))
y = v[p].value
p -= 1
z = v[n - 1].value
v[0].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p ^ e) & 3] ^ z)))
y = v[0].value
sum.value -= DELTA
rounds -= 1
def xormul(x, y):
product = 0
for i in range(len(bin(y)) - 2):
if (y & 1) != 0:
product ^= (x << i)
y >>= 1
return product
def xord(x):
product = x
for i in range(32):
if (product >> 31) & 1 != 0:
product <<= 1
product ^= 0x84A6972F
else: product <<= 1
product &= 0xFFFFFFFF
return product
def rexord(x):
product = x
for i in range(32):
if product & 1 != 0:
product ^= 0x84A6972F
product >>= 1
product ^= 0x80000000
else: product >>= 1
return product
print(hex(xord(0x98c3aeba)))
print()
print(hex(0b11101111101001001110100101100111))
print(hex(rexord(0xa755690)))
1100101
def xordivmod(x, y):
div = 0
while len(bin(x)) >= len(bin(y)) and x != 0:
div ^= 1 << (len(bin(x)) - len(bin(y)))
x ^= y << (len(bin(x)) - len(bin(y)))
return div, x
def extended_gcd(a, b):
if a == 0:
return (b, 0, 1)
else:
div, mod = xordivmod(b, a)
gcd, x, y = extended_gcd(mod, a)
return (gcd, y ^ xormul(div, x), x)
def mod_inverse(a, m):
gcd, x, y = extended_gcd(a, m)
if gcd != 1:
raise ValueError(f"The modular inverse does not exist for {a} mod {m}")
else:
return xordivmod(x, m)
print(hex(xormul(0x84A6972F, 1536173203) & 0xFFFFFFFF))
print(hex(xormul(0x84A6972F, 0x98c3aeba) & 0xFFFFFFFF))
print(hex((0x84A6972F * 0x98c3aeba) & 0xFFFFFFFF))
print(mod_inverse(0x84a6972f, 0x100000000))
def test1():
k = [1796110955, 3509588462, 2816552045, 3248073894]
v = [c_uint32(2811296470),
c_uint32(3905462903),
c_uint32(3473114362),
c_uint32(778862551),
c_uint32(1832097419),
c_uint32(1532477991),
c_uint32(1698473566),
c_uint32(2244407804),
c_uint32(3790808439),
c_uint32(3570904694),
c_uint32(1068461508),
c_uint32(223976844),]
v = [c_uint32(rexord(i.value)) for i in v]
decrypt(v, len(v), k)
decrypt(v, len(v), k)
print(b''.join([i.value.to_bytes(4, 'little') for i in v]))
def test2():
k = [1796110955, 3509588462, 2816552045, 3248073894]
v = [c_uint32(1684234849),
c_uint32(1751606885),
c_uint32(1818978921),
c_uint32(1886350957),
c_uint32(1953722993),
c_uint32(2021095029),
c_uint32(842103417),
c_uint32(909456435),
c_uint32(809056311),
c_uint32(875770417),
c_uint32(943142453),
c_uint32(57),]
encrypt(v, len(v), k)
encrypt(v, len(v), k)
print([hex(i.value) for i in v])
def test3():
k = [1796110955, 3509588462, 2816552045, 3248073894]
v = [c_uint32(2166517392), c_uint32(2308814115), c_uint32(907928798), c_uint32(416155181), c_uint32(2478635997), c_uint32(2992052781), c_uint32(2761723689), c_uint32(4081200924), c_uint32(3375441825), c_uint32(3740218937), c_uint32(3731001390), c_uint32(2820357446)]
decrypt(v, len(v), k)
print(b''.join([i.value.to_bytes(4, 'little') for i in v]))
test1()
test2()
test3()
DubheCTF{82e1e3f8-85fe469f-8499dd48-466a9d60}