安全编程:
是rust,我不太想看和调试了
010打开,发现比较有规律,尝试和png头异或得到密钥128
异或出图片
badpe:
这个题的思路之前没见过,居然能这么藏
按照外壳的思路先异或0x23
'''with open("bad_pe.exe","rb") as f:
with open("tmp","wb+") as f2: a= f.read() for i in a: f2.write((i^0x23).to_bytes(1,"little"))'''
010打开看看,发现很明显的pe结构,尝试手动修复
删除前面一段数据和末尾一段数据,发现就没有经过其他改动了,尝试运行,果真运行起来了
ida动调,发现是rc4,那就用最简单的构造11111111然后再异或ord(“1”)得到密钥,然后就可以直接解密了
enc=[46, 69, 243, 128, 183, 186, 92, 215, 47, 167,
248, 54, 163, 179, 177, 58, 37, 161, 181, 55,
151, 32, 28, 108, 185, 4, 126, 134, 158, 155,
236, 45, 190, 88, 193, 50, 101, 221, 15, 114,
125, 135, 117, 71, 218, 255, 148, 136, 89, 172,
11, 104, 142, 252, 23, 87, 78, 63, 152, 18,
201, 36, 27, 51, 72, 85, 59, 238, 198, 86,
35, 197, 139, 244, 129, 8, 99, 203, 156, 65,
82, 166, 119, 56, 100, 216, 157, 173, 217, 95,
253, 204, 41, 223, 112, 130, 116, 48, 75, 189,
140, 77, 76, 131, 235, 200, 154, 229, 144, 110,
123, 150, 115, 61, 91, 170, 240, 3, 145, 171,
195, 66, 231, 149, 138, 141, 74, 127, 199, 137,
222, 62, 188, 213, 0, 93, 124, 224, 12, 40,
247, 225, 175, 169, 132, 176, 102, 83, 31, 226,
147, 7, 33, 73, 210, 164, 196, 67, 111, 96,
57, 1, 98, 13, 10, 208, 160, 25, 211, 105,
9, 16, 106, 81, 207, 245, 230, 38, 122, 205,
250, 165, 180, 178, 153, 14, 2, 64, 168, 143,
30, 43, 24, 29, 49, 212, 219, 251, 94, 249,
182, 113, 107, 21, 60, 233, 209, 146, 241, 254,
52, 39, 34, 162, 53, 109, 84, 234, 103, 242,
214, 5, 194, 97, 184, 237, 174, 17, 191, 22,
192, 19, 26, 187, 70, 239, 232, 228, 120, 133,
227, 220, 159, 121, 79, 206, 44, 90, 80, 42,
202, 246, 68, 6, 20, 118, ]
key=[234, 173, 28, 190, 171, 93, 154, 117, 95, 188,
251, 249, 215, 122, 218, 56, 119, 119, 185, 68,
192, 132, 211, 175, 191, 177, 143, 22, 42, 76,
175, 69, 175, 56, 166]
key2=[ 234, 173, 28, 143, 154, 108, 171, 68, 102, 141,
202, 200, 230, 75, 235, 9, 70, 70, 136, 117,
241, 181, 226, 158, 142, 128, 190, 39, 27, 125,
158, 116, 62, 50, 82]
key3=[]
print(len(key)*"1")
print(0x22)
strr="th3k3y!"
for i in range(len(key2)):
key3.append(key2[i]^ord("1"))
print(key3)
real_key=[46, 69, 243, 128, 183, 186, 92, 215, 47, 167,
248, 54, 163, 179, 177, 58, 37, 161, 181, 55,
151, 32, 28, 108, 185, 4, 126, 134, 158, 155,
236, 45, 190, 88, 193, 50, 101, 221, 15, 114,
125, 135, 117, 71, 218, 255, 148, 136, 89, 172,
11, 104, 142, 252, 23, 87, 78, 63, 152, 18,
201, 36, 27, 51, 72, 85, 59, 238, 198, 86,
35, 197, 139, 244, 129, 8, 99, 203, 156, 65,
82, 166, 119, 56, 100, 216, 157, 173, 217, 95,
253, 204, 41, 223, 112, 130, 116, 48, 75, 189,
140, 77, 76, 131, 235, 200, 154, 229, 144, 110,
123, 150, 115, 61, 91, 170, 240, 3, 145, 171,
195, 66, 231, 149, 138, 141, 74, 69, 199, 137,
222, 62, 188, 213, 0, 93, 124, 224, 12, 40,
247, 225, 175, 169, 132, 176, 102, 83, 31, 226,
147, 7, 33, 73, 210, 164, 196, 67, 111, 96,
57, 1, 98, 13, 10, 208, 160, 25, 211, 105,
9, 16, 106, 81, 207, 245, 230, 38, 122, 205,
250, 165, 180, 178, 153, 14, 2, 64, 168, 143,
30, 43, 24, 29, 49, 212, 219, 251, 94, 249,
182, 113, 107, 21, 60, 233, 209, 146, 241, 254,
52, 39, 34, 162, 53, 109, 84, 234, 103, 242,
214, 5, 194, 97, 184, 237, 174, 17, 191, 22,
192, 19, 26, 187, 70, 239, 232, 228, 120, 133,
227, 220, 159, 121, 79, 206, 44, 90, 80, 42,
202, 246, 68, 6, 20, 118, ]
print(len(real_key))
a=[0xe4,0x52,0x9f,0x31,0x89,0x27,0x66,0x67,0xf3,0x68,0x90,0xfc,0xea,0xe5,0x11,0x02,0x5d,0x16,0xab,0x1e,0xe9,0x59,0xd3,0xb4,0x61,0x8d,0x11,0x17,0x19,0xe5,0x88,0x0a,0xcc,0x56,0xde,0x8e,0xd0,0x86,0x3e,0xdc,0x65,0x84,]
for i in a:
print((i),end=" ")
real_enc=[ 189, 240, 76, 217, 208, 41, 242, 70, 8, 204,
200, 159, 190, 75, 239, 103, 70, 4, 230, 50,
243, 246, 170, 240, 209, 216, 236, 117, 73, 47,
204, 38, 46, 126, 99]
print()
for i in range(len(real_enc)):
print(chr(real_enc[i]^key3[i]),end="")
babyre 先贴脚本
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
int decry1(uint32_t f1, uint32_t f2, uint32_t f3) {
unsigned int v23, v24, v25;
uint8_t row[12];
unsigned int a[32 * 6];
srand(0xDEADC0DE);
for (int r = 0; r < 32 * 6; r++) {
a[r] = rand();
}
for (int j = 31; j >= 0; --j) {
v23 = f1 >> 7;
v24 = a[4 + j * 6] + v23;
v25 = (f1 >> 15) ^ (f1 << 10) | 3;
f3 -= v24 + (a[5 + j * 6] ^ v25);
v23 = f3 >> 7;
v24 = a[2 + j * 6] + v23;
v25 = (f3 >> 15) ^ (f3 << 10) | 3;
f2 -= v24 + (a[3 + j * 6] ^ v25);
v23 = f2 >> 7;
v24 = a[j * 6] + v23;
v25 = (f2 >> 15) ^ (f2 << 10) | 3;
f1 -= v24 + (a[1 + j * 6] ^ v25);
row[0] = (uint8_t)f1;
row[1] = (uint8_t)(f1 >> 8);
row[2] = (uint8_t)(f1 >> 16);
row[3] = (uint8_t)(f1 >> 24);
row[4] = (uint8_t)f2;
row[5] = (uint8_t)(f2 >> 8);
row[6] = (uint8_t)(f2 >> 16);
row[7] = (uint8_t)(f2 >> 24);
row[8] = (uint8_t)f3;
row[9] = (uint8_t)(f3 >> 8);
row[10] = (uint8_t)(f3 >> 16);
row[11] = (uint8_t)(f3 >> 24);
for (int w = 0; w < 12; w++) {
row[w] = ((row[w] + 0x100 - 66) * 167) % 256;
}
f1 = (row[3] << 24) | (row[2] << 16) | (row[1] << 8) | row[0];
f2 = (row[7] << 24) | (row[6] << 16) | (row[5] << 8) | row[4];
f3 = (row[11] << 24) | (row[10] << 16) | (row[9] << 8) | row[8];
}
printf("%x,%x,%x", f1, f2, f3);
return 0;
}
int main()
{
/*uint32_t ida_chars[] = {
0x484D3BA0, 0x27312854,
0x6DF12135, 0x18736A4C,
0x713BBD98, 0xB65A772D,
0x0B2BCB9B, 0xE48A4CA9,
0x5C4F1BF1, 0x983D3059,
0x3F14FC7A, 0xF464022B
};*/
uint32_t ida_chars[] = {
0xA03B4D48,
0x54283127,
0x3521F16D,
0x4C6A7318,
0x98BD3B71,
0x2D775AB6,
0x9BCB2B0B,
0xA94C8AE4,
0xF11B4F5C,
0x59303D98,
0x7AFC143F,
0x2B0264F4, };
decry1(ida_chars[0], ida_chars[1], ida_chars[2]);
decry1(ida_chars[3], ida_chars[4], ida_chars[5]);
decry1(ida_chars[6], ida_chars[7], ida_chars[8]);
decry1(ida_chars[9], ida_chars[10], ida_chars[11]);
return 0;
}
直接根据逻辑硬逆 具体是srand一个种子,然后用rand生成密钥 还以为给的dllpatch过了,我还自己看了一下dll,发现没有被修改,那就直接调用标准库解密 被大小端序搞了一会儿,最开始写的大端 后来改成小端就出了,但是还要改一下顺序,4位换一下位 flag{1CpOVOIeB1d2FcYUvnN1k5PbfMzMNzUzUgV6mB7hXF}
vm:
这个题,我是赛后复现的,当时不知道怎么做,知道是vm也恢复不出源码,跟着别的师傅的wp复现一下
这是tea的密钥和密文
这里开了10个线程,虽然不知道具体是怎么实现加密的,但是start_routine是虚拟机的使用函数
因为这个指令dump出来有点困难,最开始的想法是通过idapython来打印opcode,但是好像非常的多
import ida_dbg
MyR0 = ida_dbg.get_reg_val("RAX")
print(MyR0,end=",")
手动恢复非常困难,但是由于这里的opcode我导不出来,额,就算导出来了,这里的操作数也不太容易理清,借鉴一下师傅的脚本
#!/usr/bin/env python3
codes = open('./vm', 'rb').read()[0x3020: 0x3020 + 0x157]
codes = ''.join(bin(i)[2: ].rjust(8, '0')[:: -1] for i in codes)
def fetch_imm(codes, pc, size):
assert pc + size <= len(codes)
value = int(codes[pc: pc + size][:: -1], 2)
return value, pc + size
def fetch_opcode(codes, pc):
return fetch_imm(codes, pc, 5)
def fetch_reg_index(codes, pc):
return fetch_imm(codes, pc, 4)
def fetch_imm16(codes, pc):
return fetch_imm(codes, pc, 16)
regs = ['rax', 'rbp', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15']
print('.intel_syntax noprefix')
pc = 0
while pc < len(codes):
print('_0x%04x: ' % pc, end='')
opcode, pc = fetch_opcode(codes, pc)
if opcode == 15:
dreg, pc = fetch_reg_index(codes, pc)
imm, pc = fetch_imm16(codes, pc)
print('cmp %s, 0\n jnz _0x%04x' % (regs[dreg], imm))
elif opcode == 17:
dreg, pc = fetch_reg_index(codes, pc)
sreg, pc = fetch_reg_index(codes, pc)
print('mov [%s + 0x2000], %s' % (regs[sreg], regs[dreg]))
elif opcode == 28:
print('call m_putchar')
elif opcode == 29:
print('call m_getchar')
elif opcode == 31:
print('ret')
elif opcode == 16:
dreg, pc = fetch_reg_index(codes, pc)
sreg, pc = fetch_reg_index(codes, pc)
print('mov %s, [%s + 0x2000]' % (regs[dreg], regs[sreg]))
elif opcode & 0x18 == 8:
dreg, pc = fetch_reg_index(codes, pc)
imm, pc = fetch_imm16(codes, pc)
op = ['add', 'sub', 'mov', 'shl', 'shr'][opcode & 7]
print('%s %s, 0x%x' % (op, regs[dreg], imm))
elif opcode & 0x18 == 0:
dreg, pc = fetch_reg_index(codes, pc)
sreg, pc = fetch_reg_index(codes, pc)
op = ['add', 'sub', 'mov', 'xor'][opcode & 7]
print('%s %s, %s' % (op, regs[dreg], regs[sreg]))
else:
assert False, hex(opcode)
第一次见这样的代码,太高级了,这样恢复虚拟机真的好用,然后再gcc -s main.s -o main.o
然后放ida中分析,就是一个很清晰的tea加密了,太nb了,学习了
然后解密就是小问题了,网上一找一堆
#include <stdio.h>
#include <stdint.h>
//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
uint32_t delta = 0x43217856;
sum=delta*32;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i<32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}
int main()
{
int i=0;
int j=0;
// v为要加解密的数据,两个32位无符号整数
uint32_t v[] = { 0x0FB6B1B8,0x3A84F414,0x90CE01CB,0xB4859002,0xEA807F7C,0x2D7458B7 };
uint32_t v1[]={0x90CE01CB,0xB4859002};
uint32_t v2[]={0xEA807F7C,0x2D7458B7};
// k为加解密密钥,4个32位无符号整数,密钥长度为128位
uint32_t k[4] = { 17,34,136,0xff};
int n = sizeof(v) / sizeof(uint32_t);
printf("加密前原始数据:0x%x 0x%x\n", v[0], v[1]);
//encrypt(v, k);
printf("加密后的数据:0x%x 0x%x\n", v[0], v[1]);
decrypt(v1, k);
//decrypt(v[2], k);
//decrypt(v[4], k);
printf("解密后的数据:0x%x 0x%x\n", v[0], v[1]);
for ( i = 0; i < n; i++)
{
for ( j = 0; j < sizeof(uint32_t)/sizeof(uint8_t); j++)
{
printf("%c", (v1[i] >> (j * 8)) & 0xFF);
}
}
printf("\n");
return 0;
}