VNCTF2023 | Reverse

BabyAnti

与WMCTF那道2一样
将AntiCheat和app 两个so都patch一下 重签名打包运行得到flag
image

flag{D1n0_Run_0ut_0f_The_F0rest_F1nally^_^}

PZGalaxy

在index.html找到RC4

function Leaf(k, p) {
      var s = [], j = 0, x, res = '';
      for (var i = 0; i < 256; i++) {
        s[i] = i;
      }
      for (i = 0; i < 256; i++) {
        j = (j + s[i] + k.charCodeAt(i % k.length)) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
      }
      i = 0;
      j = 0;
      for (var y = 0; y < p.length; y++) {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        x = s[i];
        s[i] = s[j];
        s[j] = x;
        res += String.fromCharCode(p.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
      }
      return res;
    }


    form.addEventListener("submit", (ev) => {
      ev.preventDefault();
  
      var date = document.getElementById('date').value;

      var enc = ['¦', 'p', ':', 'Ü', '\x92', 'Ã', '\x97', 'ó', '\x1A', 'ß', '\b', 'Ö', 'A', ' ', '5', '\x90', '{', '\x06', 'Ô', '÷', 's', '_', '\x1D', ':', 'I', 'L', 'C', 'X', 'Ñ', '¹', 'O', '\x99', '\x85', '3', 'à', 'i', '|'];
      flag = Leaf(date, enc.join(''));

      if ( flag.substring(0, 4) ==  "flag" && date.length == 8 && date.substring(0, 4) == "2023"){
        Galaxy('Neko.jpg', 50);
        alert(flag);
      } else{
        Galaxy('Fish.jpg', 50);
        alert("鱼怎么抓痒?");
      }
    })

思路就是爆破date

#include<bits/stdc++.h>
using namespace std;
signed main(){
	int base64_table[] = {166,112,58,220,146,195,151,243,26,223,8,214,65,32,53,144,123,6,212,247,115,95,29,58,73,76,67,88,209,185,79,153,133,51,224,105,124};
	string key1 = "2023";
	string table="0123456789";
	for(char c1:table){
		for(char c2:table){
			for(char c3:table){
				for(char c4:table){
					string key=key1+c1+c2+c3+c4;		
					int s[256],k[256];
				int j=0;
				for (int i = 0; i < 256; i++) {
			            s[i] = i;
			            k[i] = key[i % key.length()];
			        }
			        for (int i2 = 0; i2 < 256; i2++) {
			            j = (s[i2] + j + k[i2]) & 255;
			            int temp = s[i2];
			            s[i2] = s[j];
			            s[j] = temp;
			        }
				int j2 = 0;
			        int i3 = 0;
			        string flag="";
			        for (int i4 : base64_table) {
			            i3 = (i3 + 1) & 255;
			            j2 = (s[i3] + j2) & 255;
			            int temp2 = s[i3];
			            s[i3] = s[j2];
			            s[j2] = temp2;
			            int rnd = s[(s[i3] + s[j2]) & 255];
			            flag += ((char) ((i4 ^ rnd))&0xff);
			        }
			        if(flag[0]=='f'&&flag[1]=='l'&&flag[2]=='a'){
			        	cout<<flag<<"\n";
			        	cout<<key;
					}
				}
			}
		}
	}


}

C输出的flag有乱码 但是可以得到date 20230127
靶机提交得到flag
flag{HitYourSoulAndSeeYouInTheGalaxy}

confuse_re

... 就硬考察AES的每一步...
程序采用了一大堆 call $+5 这种 f7慢慢动调能找到所有函数
输入 bor后进入checkpasswd

unsigned __int64 __fastcall check_passwd_sub_40291F(__int64 a1, __int64 a2)
{
  char v2; // al
  char v3; // al
  unsigned __int64 result; // rax
  int i; // [rsp+4h] [rbp-28Ch]
  int j; // [rsp+4h] [rbp-28Ch]
  int k; // [rsp+4h] [rbp-28Ch]
  int l; // [rsp+4h] [rbp-28Ch]
  int m; // [rsp+4h] [rbp-28Ch]
  int n; // [rsp+4h] [rbp-28Ch]
  int v11; // [rsp+8h] [rbp-288h]
  __int64 v12[2]; // [rsp+10h] [rbp-280h]
  char v13; // [rsp+20h] [rbp-270h]
  __int64 v14[2]; // [rsp+30h] [rbp-260h] BYREF
  char v15; // [rsp+40h] [rbp-250h]
  __int64 v16[2]; // [rsp+50h] [rbp-240h]
  char v17; // [rsp+60h] [rbp-230h]
  __int64 v18[4]; // [rsp+70h] [rbp-220h]
  char v19[240]; // [rsp+90h] [rbp-200h] BYREF
  __int64 INPUT[2]; // [rsp+180h] [rbp-110h] BYREF
  char v21[232]; // [rsp+190h] [rbp-100h] BYREF
  int v22; // [rsp+278h] [rbp-18h]
  __int16 v23; // [rsp+27Ch] [rbp-14h]
  char v24; // [rsp+27Eh] [rbp-12h]
  unsigned __int64 v25; // [rsp+288h] [rbp-8h]

  v25 = __readfsqword(0x28u);
  v12[0] = 0LL;
  v12[1] = 0LL;
  v13 = 0;
  v14[0] = 0LL;
  v14[1] = 0LL;
  v15 = 0;
  v16[0] = 0LL;
  v16[1] = 0LL;
  v17 = 0;
  v18[0] = 0x153CF38D66CCDCDCLL;
  v18[1] = 0xDFD7D94616EF5E50LL;
  v18[2] = 0x39A7DC6577442750LL;
  v18[3] = 0xF64DD887B7FCB68LL;
  INPUT[0] = 0LL;
  INPUT[1] = 0LL;
  memset(v21, 0, sizeof(v21));
  v22 = 0;
  v23 = 0;
  v24 = 0;
  sub_4043D8();                                 // a2: print password:
  sub_4043F7();                                 // input
  for ( i = 0; *((_BYTE *)INPUT + i); ++i )
    ;
  if ( i == 32 )                                // len=32
  {
    for ( j = 0; j <= 15; ++j )
    {
      sub_404444();
      *((_BYTE *)v16 + j) = v2;                 // sub_4028F0
    }
    for ( k = 0; k <= 15; ++k )
    {
      *((_BYTE *)v12 + k) = *((_BYTE *)INPUT + k);// v12:input[:16]
      *((_BYTE *)v14 + k) = *((_BYTE *)&INPUT[2] + k);// v14:input[16:]
    }
    sub_404462();                               // sub_40462(v16,v19) sub_4026B0
    sub_40449B();                               // sub_40449b(v12,v19) sub_40253C
    for ( l = 0; l <= 15; ++l )
    {
      sub_4044D4();                             // v14[] = (v14[]^v12[])+1
      *((_BYTE *)v14 + l) = v3;                 // sub_4028D2:a1^a2 + 1
    }
    sub_40450C(v14, v19);                       // sub_40253C  AES
    v11 = 1;
    for ( m = 0; m <= 15; ++m )                 // check
    {
      if ( *((_BYTE *)v12 + m) != *((_BYTE *)v18 + m) )
        v11 = 0;
    }
    for ( n = 0; n <= 15; ++n )
    {
      if ( *((_BYTE *)v14 + n) != *((_BYTE *)&v18[2] + n) )
        v11 = 0;
    }
    if ( v11 == 1 )
      sub_404545();
    else
      sub_404564();
  }
  else
  {
    sub_404425(INPUT, a2);
  }
  result = __readfsqword(0x28u) ^ v25;
  if ( result )
    sub_45FE30();
  return result;
}

确实对AES的实现不是很熟悉
魔改点在这里
image

AddRoundKey 的时候多xor了一个0x23

这个函数
image

是扩展轮密钥的时候的标准函数
image

image

所以key就是 v16 动调提取出来
但我c的AES要炸... 找python的跑一跑

import re
import binascii

class Aes:
    sbox = [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
        0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
        0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
        0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
        0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
        0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
        0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
        0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
    s_box = {}
    ns_box = {   }

    Rcon = { 
        1: ['0x01', '0x00', '0x00', '0x00'],
        2: ['0x02', '0x00', '0x00', '0x00'],
        3: ['0x04', '0x00', '0x00', '0x00'],
        4: ['0x08', '0x00', '0x00', '0x00'],
        5: ['0x10', '0x00', '0x00', '0x00'],
        6: ['0x20', '0x00', '0x00', '0x00'],
        7: ['0x40', '0x00', '0x00', '0x00'],
        8: ['0x80', '0x00', '0x00', '0x00'],
        9: ['0x1B', '0x00', '0x00', '0x00'],
        10: ['0x36', '0x00', '0x00', '0x00']
    }
    Matrix = [
        ['0x02', '0x03', '0x01', '0x01'],
        ['0x01', '0x02', '0x03', '0x01'],
        ['0x01', '0x01', '0x02', '0x03'],
        ['0x03', '0x01', '0x01', '0x02']
    ]
    ReMatrix = [
        ['0x0e', '0x0b', '0x0d', '0x09'],
        ['0x09', '0x0e', '0x0b', '0x0d'],
        ['0x0d', '0x09', '0x0e', '0x0b'],
        ['0x0b', '0x0d', '0x09', '0x0e']
    ]
    plaintext = [[], [], [], []]
    plaintext1 = [[], [], [], []]
    subkey = [[], [], [], []]  

    def __init__(self, key): 
        self.s_box = dict(zip(["0x%02x"%i for i in range(256)], ["0x%02x"%i for i in self.sbox])) 
        self.ns_box = dict(zip(self.s_box.values(), self.s_box.keys()))
        for i in range(4):
            for j in range(0, 8, 2):
                self.subkey[i].append("0x" + key[i * 8 + j:i * 8 + j + 2]) 
        # print(self.subkey)
        for i in range(4, 44): 
            if i % 4 != 0: 
                tmp = xor_32(self.subkey[i - 1], self.subkey[i - 4],0)
                self.subkey.append(tmp)
            else:  # 4的倍数的时候执行
                tmp1 = self.subkey[i - 1][1:]
                tmp1.append(self.subkey[i - 1][0])
                # print(tmp1)
                for m in range(4):
                    tmp1[m] = self.s_box[tmp1[m]]
                # tmp1 = self.s_box['cf'] 
                tmp1 = xor_32(tmp1, self.Rcon[i / 4], 0) 
                self.subkey.append(xor_32(tmp1, self.subkey[i - 4],0))
        # print(self.subkey)

    def AddRoundKey(self, round): 
        for i in range(4):
            self.plaintext[i] = xor_32(self.plaintext[i], self.subkey[round * 4 + i],0x23)
        # print('AddRoundKey',self.plaintext)

    def PlainSubBytes(self): 
        for i in range(4):
            for j in range(4):
                self.plaintext[i][j] = self.s_box[self.plaintext[i][j]]
        # print('PlainSubBytes',self.plaintext)

    def RePlainSubBytes(self): 
        for i in range(4):
            for j in range(4):
                self.plaintext[i][j] = self.ns_box[self.plaintext[i][j]]

    def ShiftRows(self): 
        p1, p2, p3, p4 = self.plaintext[0][1], self.plaintext[1][1], self.plaintext[2][1], self.plaintext[3][1]
        self.plaintext[0][1] = p2
        self.plaintext[1][1] = p3
        self.plaintext[2][1] = p4
        self.plaintext[3][1] = p1
        p1, p2, p3, p4 = self.plaintext[0][2], self.plaintext[1][2], self.plaintext[2][2], self.plaintext[3][2]
        self.plaintext[0][2] = p3
        self.plaintext[1][2] = p4
        self.plaintext[2][2] = p1
        self.plaintext[3][2] = p2
        p1, p2, p3, p4 = self.plaintext[0][3], self.plaintext[1][3], self.plaintext[2][3], self.plaintext[3][3]
        self.plaintext[0][3] = p4
        self.plaintext[1][3] = p1
        self.plaintext[2][3] = p2
        self.plaintext[3][3] = p3
        # print('ShiftRows',self.plaintext)

    def ReShiftRows(self): 
        p1, p2, p3, p4 = self.plaintext[0][1], self.plaintext[1][1], self.plaintext[2][1], self.plaintext[3][1]
        self.plaintext[3][1] = p3
        self.plaintext[2][1] = p2
        self.plaintext[0][1] = p4
        self.plaintext[1][1] = p1
        p1, p2, p3, p4 = self.plaintext[0][2], self.plaintext[1][2], self.plaintext[2][2], self.plaintext[3][2]
        self.plaintext[0][2] = p3
        self.plaintext[1][2] = p4
        self.plaintext[2][2] = p1
        self.plaintext[3][2] = p2
        p1, p2, p3, p4 = self.plaintext[0][3], self.plaintext[1][3], self.plaintext[2][3], self.plaintext[3][3]
        self.plaintext[0][3] = p2
        self.plaintext[1][3] = p3
        self.plaintext[2][3] = p4
        self.plaintext[3][3] = p1

    def MixColumns(self): 
        for i in range(4):
            for j in range(4):
                self.plaintext1[i].append(MatrixMulti(self.Matrix[j], self.plaintext[i]))
        # print('MixColumns',self.plaintext1)

    def ReMixColumns(self): 
        for i in range(4):
            for j in range(4):
                self.plaintext1[i].append(MatrixMulti(self.ReMatrix[j], self.plaintext[i]))

    def AESEncryption(self, plaintext): 
        self.plaintext = [[], [], [], []]
        for i in range(4):
            for j in range(0, 8, 2):
                self.plaintext[i].append("0x" + plaintext[i * 8 + j:i * 8 + j + 2])
        self.AddRoundKey(0)
        for i in range(9):
            self.PlainSubBytes()
            self.ShiftRows()
            self.MixColumns()
            self.plaintext = self.plaintext1
            self.plaintext1 = [[], [], [], []]
            self.AddRoundKey(i + 1)

        self.PlainSubBytes()
        self.ShiftRows()
        self.AddRoundKey(10) 
        return Matrixtostr(self.plaintext)

    def AESDecryption(self, cipher): 
        self.plaintext = [[], [], [], []]
        for i in range(4):
            for j in range(0, 8, 2):
                self.plaintext[i].append('0x' + cipher[i * 8 + j:i * 8 + j + 2]) 

        # print(self.ns_box)
        self.AddRoundKey(10)
        for i in range(9):
            self.ReShiftRows()
            self.RePlainSubBytes()
            self.AddRoundKey(9-i)
            self.ReMixColumns()
            self.plaintext = self.plaintext1
            self.plaintext1 = [[], [], [], []]
        self.ReShiftRows()
        self.RePlainSubBytes()
        self.AddRoundKey(0)
        return Matrixtostr(self.plaintext)

    def Encryption(self, text): 
        group = PlaintextGroup(TextToByte(text), 32, 1)
        # print(group)
        cipher = ""
        for i in range(len(group)):
            cipher = cipher + self.AESEncryption(group[i])
        return cipher

    def Decryption(self, cipher): 
        group = PlaintextGroup(cipher, 32, 0)
        # print(group)
        text = ''
        for i in range(len(group)):
            text = text + self.AESDecryption(group[i])
        text = ByteToText(text)
        return text


def xor_32(start, end, key): 
    a = []
    for i in range(0, 4):
        xor_tmp = ""
        b = hextobin(start[i])
        c = hextobin(end[i])
        d = bin(key)[2:].rjust(8,'0')
        for j in range(8):
            tmp = int(b[j], 10) ^ int(c[j], 10) ^ int(d[j],10)
            xor_tmp += str(tmp )
        a.append(bintohex(xor_tmp))
    return a


def xor_8(begin, end): 
    xor_8_tmp = ""
    for i in range(8):
        xor_8_tmp += str(int(begin[i]) ^ int(end[i]))
    return xor_8_tmp


def hextobin(word): 
    word = bin(int(word, 16))[2:]
    for i in range(0, 8-len(word)): 
        word = '0'+word
    return word

def bintohex(word): 
    word = hex(int(word, 2))
    if len(word) == 4:
        return word
    elif len(word) < 4:
        return word.replace('x', 'x0')


def MatrixMulti(s1, s2): 
    result = []
    s3 = []
    for i in range(4):
        s3.append(hextobin(s2[i])) 
    for i in range(4):
        result.append(MultiProcess(int(s1[i], 16), s3[i]))
    for i in range(3):
        result[0] = xor_8(result[0], result[i+1])
    return bintohex(result[0])


def MultiProcess(a, b): 
    if a == 1:
        return b
    elif a == 2:
        if b[0] == '0':
            b = b[1:] + '0'
        else:
            b = b[1:] + '0'
            b = xor_8(b, '00011011')
        return b
    elif a == 3:
        tmp_b = b
        if b[0] == '0':
            b = b[1:] + '0'
        else:
            b = b[1:] + '0'
            b = xor_8(b, '00011011')
        return xor_8(b, tmp_b)

    elif a == 9:
        tmp_b = b
        return xor_8(tmp_b, MultiProcess(2, MultiProcess(2, MultiProcess(2, b))))
    elif a == 11:
        tmp_b = b
        return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, b)))
    elif a == 13:
        tmp_b = b
        return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))
    elif a == 14:
        return xor_8(MultiProcess(2, b), xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))


def Matrixtostr(matrix): 
    result = ""
    for i in range(4):
        for j in range(4):
            result += matrix[i][j][2:]
    return result


def PlaintextGroup(plaintext, length, flag): 
    group = re.findall('.{'+str(length)+'}', plaintext)
    group.append(plaintext[len(group)*length:])
    if group[-1] == '' and flag:
        group[-1] = '16161616161616161616161616161616'
    elif len(group[-1]) < length and flag:
        tmp = int((length-len(group[-1])) / 2)
        if tmp < 10:
            for i in range(tmp):
                group[-1] = group[-1] + '0'+str(tmp)
        else:
            for i in range(tmp):
                group[-1] = group[-1] + str(tmp)
    elif not flag:
        del group[-1]
    return group


def TextToByte(words): 
    text = words.encode('utf-8').hex()
    return text


def ByteToText(encode): 
    tmp = int(encode[-2:])
    word = ''
    for i in range(len(encode)-tmp*2):
        word = word + encode[i]
    # print(word)
    word = bytes.decode(binascii.a2b_hex(word))
    return word
def xorbytes(bytes1,bytes2):
    length=min(len(bytes1),len(bytes2))
    output=bytearray()
    for i in range(length):
        output.append(bytes1[i]^bytes2[i])
    return bytes(output)

res='DCDCCC668DF33C15505EEF1646D9D7DF5027447765DCA73968CB7F7B88DD640F'.lower()
key = 'CA9D7FF8A4099004FAD40661E93B775A'.lower()
A1 = Aes(key)
p1 = A1.AESDecryption(res[:32])
p2 = A1.AESDecryption(res[32:])
from Crypto.Util.number import *
p1 = long_to_bytes(int(p1,16))
p2 = long_to_bytes(int(p2,16))
flag = p1.decode()
p1 = long_to_bytes(int(res[:32],16))
for i in range(len(p2)):
    flag += chr(((p2[i]-1)^p1[i])&0xff)
print(flag)

VNCTF{fa9ad36bd2de1586d944cf7b2935dd91}

jijiji

附件下载不了...

dll_puzzle

好题!
这题加了一大堆反调试... 再加上是dll 狗都不动调...
image

SM4~

注意到有TlsCallback 先看Tls
image

有两个分支 分别进入看看 猜测出来下面那个sub_1000A670为真正分支
image

可以猜出来这里的xor是在生成SM4 SBOX
由最后的check 结合标准Sbox
image

正是标准的SM4

进入DllEntry -> DllMain
image

看汇编发现还有很多没有反编译 把 ret 9 patch掉

最后还有一处花指令
image

典型的jz jnz patch掉

start = 0x10001000
end = 0x10009000
while start<end:
    if((get_wide_byte(start)==0x74) and (get_wide_byte(start+2)==0x75)):
        ida_bytes.patch_byte(start+4,0x90)
    start += 1
print("[+] OK !")

得到 sub_10001BA2
image

很容易知道是flag的check
回到前面
这里可以通过SM4_CK表引用得到SM4函数
image

往前找 SM4_key
image

image

这里的v42可以由后面的check算出来==42
将数据xor 42即可得到key
然后z3解出SM4的密文
注意要 Bitvec(16) 然后加 0~0xff的约束 因为z3设置的bit长度是整个过程都不能超过的 也就是会随时取模256
得到hex的密文 cyberchef一把梭
image

flag{3f27d7470d8967fd344ec7f1261e64b3}

posted @ 2024-02-18 16:26  N0zoM1z0  阅读(21)  评论(0编辑  收藏  举报