BUUCTF reverse wp 86 - 90

[GWCTF 2019]babyvm

在这里插入图片描述

void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
  __int64 v3[2]; // [rsp+10h] [rbp-10h] BYREF

  v3[1] = __readfsqword(0x28u);
  v3[0] = 0LL;
  puts("Please input something:");
  sub_CD1(v3);
  sub_E0B(v3);
  sub_F83(v3);
  puts("And the flag is GWHT{true flag}");
  exit(0);
}

unsigned __int64 __fastcall sub_CD1(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  *(_DWORD *)a1 = 0;
  *(_DWORD *)(a1 + 4) = 18;
  *(_DWORD *)(a1 + 8) = 0;
  *(_DWORD *)(a1 + 12) = 0;
  *(_QWORD *)(a1 + 16) = &unk_202060;
  *(_BYTE *)(a1 + 24) = -15;
  *(_QWORD *)(a1 + 32) = sub_B5F;
  *(_BYTE *)(a1 + 40) = -14;
  *(_QWORD *)(a1 + 48) = sub_A64;
  *(_BYTE *)(a1 + 56) = -11;
  *(_QWORD *)(a1 + 64) = sub_AC5;
  *(_BYTE *)(a1 + 72) = -12;
  *(_QWORD *)(a1 + 80) = sub_956;
  *(_BYTE *)(a1 + 88) = -9;
  *(_QWORD *)(a1 + 96) = sub_A08;
  *(_BYTE *)(a1 + 104) = -8;
  *(_QWORD *)(a1 + 112) = sub_8F0;
  *(_BYTE *)(a1 + 120) = -10;
  *(_QWORD *)(a1 + 128) = sub_99C;
  qword_2022A8 = malloc(0x512uLL);
  memset(qword_2022A8, 0, 0x512uLL);
  return __readfsqword(0x28u) ^ v2;
}

unsigned __int64 __fastcall sub_E0B(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  *(_QWORD *)(a1 + 16) = &unk_202060;
  while ( **(_BYTE **)(a1 + 16) != 0xF4 )
    sub_E6E(a1);
  return __readfsqword(0x28u) ^ v2;
}

unsigned __int64 sub_F83()
{
  int i; // [rsp+Ch] [rbp-14h]
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  for ( i = 0; dword_2022A4 - 1 > i; ++i )
  {
    if ( *((_BYTE *)qword_2022A8 + i + 32) != aFzAmAmFmtSum[i] )
    {
      puts("WRONG!");
      exit(0);
    }
  }
  puts("Congratulation?");
  puts("tips: input is the start");
  return __readfsqword(0x28u) ^ v2;
}

sub_CD1是自定义的VM, 先逆出所有指令
mov: E1, E2, E3, E4, E5, E7

unsigned __int64 __fastcall sub_B5F(__int64 a1)
{
  int *v2; // [rsp+28h] [rbp-18h]
  unsigned __int64 v3; // [rsp+38h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  v2 = (int *)(*(_QWORD *)(a1 + 16) + 2LL);
  switch ( *(_BYTE *)(*(_QWORD *)(a1 + 16) + 1LL) )
  {
    case 0xE1:
      *(_DWORD *)a1 = *((char *)qword_2022A8 + *v2);
      break;
    case 0xE2:
      *(_DWORD *)(a1 + 4) = *((char *)qword_2022A8 + *v2);
      break;
    case 0xE3:
      *(_DWORD *)(a1 + 8) = *((char *)qword_2022A8 + *v2);
      break;
    case 0xE4:
      *((_BYTE *)qword_2022A8 + *v2) = *(_DWORD *)a1;
      break;
    case 0xE5:
      *(_DWORD *)(a1 + 12) = *((char *)qword_2022A8 + *v2);
      break;
    case 0xE7:
      *((_BYTE *)qword_2022A8 + *v2) = *(_DWORD *)(a1 + 4);
      break;
    default:
      break;
  }
  *(_QWORD *)(a1 + 16) += 6LL;
  return __readfsqword(0x28u) ^ v3;
}

xor

unsigned __int64 __fastcall sub_A64(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  *(_DWORD *)a1 ^= *(_DWORD *)(a1 + 4);
  ++*(_QWORD *)(a1 + 16);
  return __readfsqword(0x28u) ^ v2;
}

length check

unsigned __int64 __fastcall sub_AC5(__int64 a1)
{
  const char *buf; // [rsp+10h] [rbp-10h]
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  buf = (const char *)qword_2022A8;
  read(0, qword_2022A8, 0x20uLL);
  length = strlen(buf);
  if ( length != 21 )
  {
    puts("WRONG!");
    exit(0);
  }
  ++*(_QWORD *)(a1 + 16);
  return __readfsqword(0x28u) ^ v3;
}

nop

unsigned __int64 __fastcall sub_956(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  ++*(_QWORD *)(a1 + 16);
  return __readfsqword(0x28u) ^ v2;
}

mul

unsigned __int64 __fastcall sub_A08(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  *(_DWORD *)a1 *= *(_DWORD *)(a1 + 12);
  ++*(_QWORD *)(a1 + 16);
  return __readfsqword(0x28u) ^ v2;
}

swap

unsigned __int64 __fastcall sub_8F0(int *a1)
{
  int v2; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  v2 = *a1;
  *a1 = a1[1];
  a1[1] = v2;
  ++*((_QWORD *)a1 + 2);
  return __readfsqword(0x28u) ^ v3;
}

special calculation

unsigned __int64 __fastcall sub_99C(__int64 a1)
{
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  *(_DWORD *)a1 = *(_DWORD *)(a1 + 8) + 2 * *(_DWORD *)(a1 + 4) + 3 * *(_DWORD *)a1;
  ++*(_QWORD *)(a1 + 16);
  return __readfsqword(0x28u) ^ v2;
}

unk_202060是操作码, 提取出来, 按照刚刚逆向分析出来的指令, 写脚本解析VM代码
这里a1是eax, a1+4是ebx, a1+8是ecx, a1+12是edx, a1+16是eip
在这里插入图片描述

opcode = [
    0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
    0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00, 
    0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 
    0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00, 
    0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23, 
    0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2, 
    0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 
    0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1, 
    0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00, 
    0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
    0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00, 
    0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
    0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00, 
    0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
    0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00, 
    0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C, 
    0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00, 
    0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D, 
    0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2, 
    0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00, 
    0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1, 
    0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00, 
    0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
    0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00, 
    0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
    0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00, 
    0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1, 
    0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00, 
    0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1, 
    0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00, 
    0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 
    0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2, 
    0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00, 
    0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1, 
    0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 
    0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 
    0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00, 
    0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05, 
    0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1, 
    0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00, 
    0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1, 
    0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 
    0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09, 
    0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 
    0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 
    0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1, 
    0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 
    0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1, 
    0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00, 
    0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7, 
    0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 
    0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E, 
    0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1, 
    0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00, 
    0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7, 
    0x11, 0x00, 0x00, 0x00, 0xF4
]

i = 0
while i < len(opcode):
	if (opcode[i] == 0xF1):
		print('mov ', end='')
		if (opcode[i + 1] == 0xE1):
			print('eax ' + 'flag[' + str(opcode[i + 2]) + ']')
		elif (opcode[i + 1] == 0xE2):
			print('ebx ' + 'flag[' + str(opcode[i + 2]) + ']')
		elif (opcode[i + 1] == 0xE3):
			print('ecx ' + 'flag[' + str(opcode[i + 2]) + ']')
		elif (opcode[i + 1] == 0xE4):
			print('flag[' + str(opcode[i + 2]) + '] ' + 'eax')
		elif (opcode[i + 1] == 0xE5):
			print('edx ' + 'flag[' + str(opcode[i + 2]) + ']')
		elif (opcode[i + 1] == 0xE7):
			print('flag[' + str(opcode[i + 2]) + '] ' + 'ebx')
		i += 6
	elif (opcode[i] == 0xF2):
		print('xor eax, ebx')
		i += 1
	elif (opcode[i] == 0xF5):
		print('check length')
		i += 1
	elif (opcode[i] == 0xF4):
		print('nop')
		i += 1
	elif (opcode[i] == 0xF7):
		print('mul eax, edx')
		i += 1
	elif (opcode[i] == 0xF8):
		print('swap eax, ebx')
		i += 1
	elif (opcode[i] == 0xF6):
		print('mov eax, 3*eax + 2*ebx + ecx')
		i += 1
	else:
		i += 1

得到vm指令序列, 第一段因为flag长度大于21, 所以不合法. 主要逻辑是第二段

# invalid code
check length
mov eax flag[0] 
xor eax, ebx    
mov flag[32] eax
mov eax flag[1] 
xor eax, ebx    
mov flag[33] eax
mov eax flag[2] 
xor eax, ebx    
mov flag[34] eax
mov eax flag[3] 
xor eax, ebx    
mov flag[35] eax
mov eax flag[4] 
xor eax, ebx    
mov flag[36] eax
mov eax flag[5] 
xor eax, ebx
mov flag[37] eax
mov eax flag[6]
xor eax, ebx
mov flag[38] eax
mov eax flag[7]
xor eax, ebx
mov flag[39] eax
mov eax flag[8]
xor eax, ebx
mov flag[40] eax
mov eax flag[9]
xor eax, ebx
mov flag[41] eax
mov eax flag[10]
xor eax, ebx
mov flag[42] eax
mov eax flag[11]
xor eax, ebx
mov flag[43] eax
mov eax flag[12]
xor eax, ebx
mov flag[44] eax
mov eax flag[13]
xor eax, ebx
mov flag[45] eax
mov eax flag[14]
xor eax, ebx
mov flag[46] eax
mov eax flag[15]
xor eax, ebx
mov flag[47] eax
mov eax flag[16]
xor eax, ebx
mov flag[48] eax
mov eax flag[17]
xor eax, ebx
mov flag[49] eax
mov eax flag[18]
xor eax, ebx
mov flag[50] eax
mov eax flag[19]
xor eax, ebx
mov flag[51] eax
nop

# real code
check length
mov eax flag[0]
mov ebx flag[1]
xor eax, ebx
mov flag[0] eax
mov eax flag[1]
mov ebx flag[2]
xor eax, ebx
mov flag[1] eax
mov eax flag[2]
mov ebx flag[3]
xor eax, ebx
mov flag[2] eax
mov eax flag[3]
mov ebx flag[4]
xor eax, ebx
mov flag[3] eax
mov eax flag[4]
mov ebx flag[5]
xor eax, ebx
mov flag[4] eax
mov eax flag[5]
mov ebx flag[6]
xor eax, ebx
mov flag[5] eax
mov eax flag[6]
mov ebx flag[7]
mov ecx flag[8]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[6] eax
mov eax flag[7]
mov ebx flag[8]
mov ecx flag[9]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[7] eax
mov eax flag[8]
mov ebx flag[9]
mov ecx flag[10]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[8] eax
mov eax flag[13]
mov ebx flag[19]
swap eax, ebx
mov flag[13] eax
mov flag[19] ebx
mov eax flag[14]
mov ebx flag[18]
swap eax, ebx
mov flag[14] eax
mov flag[18] ebx
mov eax flag[15]
mov ebx flag[17]
swap eax, ebx
mov flag[15] eax
mov flag[17] ebx
nop

人工转等价python代码

flag = ''    
for i in range(6):
    flag[i] = flag[i] ^ flag[i + 1]
flag[6] = (flag[8] + 2 * flag[7] + 3 * flag[6]) * flag[12]
flag[7] = (flag[9] + 2 * flag[8] + 3 * flag[7]) * flag[12]
flag[8] = (flag[10] + 2 * flag[9] + 3 * flag[8]) * flag[12]
swap(flag[13], flag[19])
swap(flag[14], flag[18])
swap(flag[15], flag[17])

拿到checklist, 然后逆回去, 注意这里伪代码有点问题, 看汇编来确认
在这里插入图片描述

checkval = [
    0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72, 
    0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72
]


checkval[13], checkval[19] = checkval[19], checkval[13]
checkval[14], checkval[18] = checkval[18], checkval[14]
checkval[15], checkval[17] = checkval[17], checkval[15]

check12 = checkval[12]
for i in range(128):
    if checkval[8] == ((checkval[10] + 2 * checkval[9] + 3 * i) * check12) & 0xFF:
        checkval[8] = i
        for j in range(128):
            if checkval[7] == ((checkval[9] + 2 * checkval[8] + 3 * j) * check12) & 0xFF:
                checkval[7] = j
                for k in range(128):
                    if checkval[6] == ((checkval[8] + 2 * checkval[7] + 3 * k) * check12) & 0xFF:
                        checkval[6] = k

for i in range(6)[::-1]:
    checkval[i] ^= checkval[i + 1]

flag = ''
for i in range(len(checkval)):
    flag += chr(checkval[i])

print('flag{{{}}}'.format(flag))

[网鼎杯 2020 青龙组]bang

APK查壳
在这里插入图片描述

Frida脱壳, 需要配置frida环境, 参考链接
在这里插入图片描述

安装frida远程环境
在这里插入图片描述

脱壳脚本 https://github.com/hluwa/FRIDA-DEXDump

脱壳之后拖进JEB打开, flag是明文形式存储…

[SUCTF2018]babyre

在这里插入图片描述

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  char *v3; // rdi
  __int64 i; // rcx
  char v6; // [rsp+0h] [rbp-20h] BYREF
  char v7[32]; // [rsp+30h] [rbp+10h]
  char v8[184]; // [rsp+50h] [rbp+30h] BYREF
  char v9[60]; // [rsp+108h] [rbp+E8h] BYREF
  unsigned int v10[8]; // [rsp+144h] [rbp+124h] BYREF
  int j; // [rsp+164h] [rbp+144h]
  int v12; // [rsp+234h] [rbp+214h]
  int v13; // [rsp+238h] [rbp+218h]

  v3 = &v6;
  for ( i = 150i64; i; --i )
  {
    *(_DWORD *)v3 = -858993460;
    v3 += 4;
  }
  j___CheckForDebuggerJustMyCode(&unk_140023035, argv, envp);
  v7[0] = 2;
  v7[1] = 3;
  v7[2] = 2;
  v7[3] = 1;
  v7[4] = 4;
  v7[5] = 7;
  v7[6] = 4;
  v7[7] = 5;
  v7[8] = 10;
  v7[9] = 11;
  v7[10] = 10;
  v7[11] = 9;
  v7[12] = 14;
  v7[13] = 15;
  v7[14] = 12;
  v7[15] = 13;
  v7[16] = 16;
  v7[17] = 19;
  v7[18] = 16;
  v7[19] = 17;
  v7[20] = 20;
  v7[21] = 23;
  v7[22] = 22;
  v7[23] = 19;
  v7[24] = 28;
  v7[25] = 25;
  v7[26] = 30;
  v7[27] = 31;
  v7[28] = 28;
  v7[29] = 25;
  v7[30] = 26;
  v7[31] = 31;
  qmemcpy(v8, "$!\"'$!\"#().+$-&/81:;4=>7092;<567HIBBDDFGHIJJMMONPPRSUTVWYYZ[\\]^^``ccdeggiikklmnnpprstuwwxy{{}}", 94);
  v8[94] = 127;
  v8[95] = 127;
  v8[96] = -127;
  v8[97] = -127;
  v8[98] = -125;
  v8[99] = -125;
  v8[100] = -116;
  v8[101] = -115;
  v8[102] = -114;
  v8[103] = -113;
  v8[104] = -120;
  v8[105] = -119;
  v8[106] = -118;
  v8[107] = -117;
  v8[108] = -116;
  v8[109] = -115;
  v8[110] = -114;
  v8[111] = -121;
  v8[112] = -104;
  v8[113] = -111;
  v8[114] = -110;
  v8[115] = -109;
  v8[116] = -108;
  v8[117] = -107;
  v8[118] = -106;
  v8[119] = -105;
  v8[120] = -104;
  v8[121] = -103;
  v8[122] = -102;
  v8[123] = -102;
  v8[124] = -100;
  v8[125] = -100;
  v8[126] = -98;
  v8[127] = -98;
  v8[128] = -96;
  v8[129] = -96;
  v8[130] = -94;
  v8[131] = -94;
  v8[132] = -92;
  v8[133] = -92;
  v8[134] = -90;
  v8[135] = -90;
  v8[136] = -88;
  v8[137] = -88;
  v8[138] = -86;
  v8[139] = -86;
  v8[140] = -84;
  v8[141] = -84;
  v8[142] = -82;
  v8[143] = -82;
  v8[144] = -80;
  v8[145] = -79;
  v8[146] = -78;
  v8[147] = -77;
  memset(v9, 0, 0x1Fui64);
  sub_140011159(std::cout, "flag format: SUCTF{xxxxxxxxxxxxxxx}\n");
  sub_140011159(std::cout, "Please Input Key:");
  std::istream::operator>>(std::cin, v10);
  v10[0] %= 0x10000u;
  v9[30] = 8;
  while ( v9[30] )
  {
    --v9[30];
    for ( j = 22; j; v9[j] |= v13 << v9[30] )
    {
      v12 = v7[22 * v9[30] + --j];
      v13 = (v12 >> ((v10[0] >> (2 * v9[30])) & 3)) & 1;
    }
  }
  sub_140011159(std::cout, v9);
  system("pause");
  return 0;
}

输入flag, 范围在0x10000之内, 直接爆破

/*
v186 %= 0x10000u;
  v185 = 8;
  while ( v185 )
  {
    --v185;
    for ( j = 22; j; v184[j] |= v189 << v185 )
    {
      v188 = *(&v4 + 22 * v185 + --j);
      v189 = (v188 >> ((v186 >> 2 * v185) & 3)) & 1;
    }
  }
*/
#include<stdio.h>
#include<string.h>
int v[500];
int v184[100];
int v188,v189;
void init();

int main() {
    init();
    for(int v186 = 0;v186 < 0x10000;v186++)
    {
        memset(v184,0,sizeof(v184));
        int v185 = 8;
        while ( v185 ) {
            --v185;
            for (int j = 22; j; v184[j] |= v189 << v185 ) {
                v188 = v[22 * v185 + --j + 4];
                v189 = (v188 >> ((v186 >> 2 * v185) & 3)) & 1;
            }
        }
        // SUCTF{xxxxxxxxxxxxxxx}
        if (v184[0] == 'S' &&
        v184[1] == 'U' &&
        v184[2] == 'C' &&
        v184[3] == 'T' &&
        v184[4] == 'F' &&
        v184[5] == '{' &&
        v184[21] == '}') {
            printf("key : %d\n",v186);
            for(int i = 0;i < 22;i++) {
                printf("%c",v184[i]);
            }
            printf("\n");
        }
    }

    return 0;
}

void init() {
    v[4]= 2;
    v[5]= 3;
    v[6]= 2;
    v[7]= 1;
    v[8]= 4;
    v[9]= 7;
    v[10]= 4;
    v[11]= 5;
    v[12]= 10;
    v[13]= 11;
    v[14]= 10;
    v[15]= 9;
    v[16]= 14;
    v[17]= 15;
    v[18]= 12;
    v[19]= 13;
    v[20]= 16;
    v[21]= 19;
    v[22]= 16;
    v[23]= 17;
    v[24]= 20;
    v[25]= 23;
    v[26]= 22;
    v[27]= 19;
    v[28]= 28;
    v[29]= 25;
    v[30]= 30;
    v[31]= 31;
    v[32]= 28;
    v[33]= 25;
    v[34]= 26;
    v[35]= 31;
    v[36]= 36;
    v[37]= 33;
    v[38]= 34;
    v[39]= 39;
    v[40]= 36;
    v[41]= 33;
    v[42]= 34;
    v[43]= 35;
    v[44]= 40;
    v[45]= 41;
    v[46]= 46;
    v[47]= 43;
    v[48]= 36;
    v[49]= 45;
    v[50]= 38;
    v[51]= 47;
    v[52]= 56;
    v[53]= 49;
    v[54]= 58;
    v[55]= 59;
    v[56]= 52;
    v[57]= 61;
    v[58]= 62;
    v[59]= 55;
    v[60]= 48;
    v[61]= 57;
    v[62]= 50;
    v[63]= 59;
    v[64]= 60;
    v[65]= 53;
    v[66]= 54;
    v[67]= 55;
    v[68]= 72;
    v[69]= 73;
    v[70]= 66;
    v[71]= 66;
    v[72]= 68;
    v[73]= 68;
    v[74]= 70;
    v[75]= 71;
    v[76]= 72;
    v[77]= 73;
    v[78]= 74;
    v[79]= 74;
    v[80]= 77;
    v[81]= 77;
    v[82]= 79;
    v[83]= 78;
    v[84]= 80;
    v[85]= 80;
    v[86]= 82;
    v[87]= 83;
    v[88]= 85;
    v[89]= 84;
    v[90]= 86;
    v[91]= 87;
    v[92]= 89;
    v[93]= 89;
    v[94]= 90;
    v[95]= 91;
    v[96]= 92;
    v[97]= 93;
    v[98]= 94;
    v[99]= 94;
    v[100]= 96;
    v[101]= 96;
    v[102]= 99;
    v[103]= 99;
    v[104]= 100;
    v[105]= 101;
    v[106]= 103;
    v[107]= 103;
    v[108]= 105;
    v[109]= 105;
    v[110]= 107;
    v[111]= 107;
    v[112]= 108;
    v[113]= 109;
    v[114]= 110;
    v[115]= 110;
    v[116]= 112;
    v[117]= 112;
    v[118]= 114;
    v[119]= 115;
    v[120]= 116;
    v[121]= 117;
    v[122]= 119;
    v[123]= 119;
    v[124]= 120;
    v[125]= 121;
    v[126]= 123;
    v[127]= 123;
    v[128]= 125;
    v[129]= 125;
    v[130]= 127;
    v[131]= 127;
    v[132]= -127;
    v[133]= -127;
    v[134]= -125;
    v[135]= -125;
    v[136]= -116;
    v[137]= -115;
    v[138]= -114;
    v[139]= -113;
    v[140]= -120;
    v[141]= -119;
    v[142]= -118;
    v[143]= -117;
    v[144]= -116;
    v[145]= -115;
    v[146]= -114;
    v[147]= -121;
    v[148]= -104;
    v[149]= -111;
    v[150]= -110;
    v[151]= -109;
    v[152]= -108;
    v[153]= -107;
    v[154]= -106;
    v[155]= -105;
    v[156]= -104;
    v[157]= -103;
    v[158]= -102;
    v[159]= -102;
    v[160]= -100;
    v[161]= -100;
    v[162]= -98;
    v[163]= -98;
    v[164]= -96;
    v[165]= -96;
    v[166]= -94;
    v[167]= -94;
    v[168]= -92;
    v[169]= -92;
    v[170]= -90;
    v[171]= -90;
    v[172]= -88;
    v[173]= -88;
    v[174]= -86;
    v[175]= -86;
    v[176]= -84;
    v[177]= -84;
    v[178]= -82;
    v[179]= -82;
    v[180]= -80;
    v[181]= -79;
    v[182]= -78;
    v[183]= -77;
}

[HDCTF2019]MFC

在这里插入图片描述

VMP, 瞳孔地震(bushi
MFC逆向使用xspy, 去52下一个

在这里插入图片描述

Windows编程, 给API发消息触发key控件

#include "stdafx.h"
#include <windows.h>
#include<stdio.h>


int _tmain(int argc, _TCHAR* argv[])
{
	HWND h = FindWindowA(NULL, "Flag就在控件里");
	SendMessage(h, 0x0464, 0, 0);

	return 0;
}

在这里插入图片描述

HWND: 944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b
DES解密就是flag

[SCTF2019]creakme

在这里插入图片描述

int __cdecl main(int argc, const char **argv, const char **envp)
{
  HMODULE ModuleHandleW; // eax
  int v4; // eax
  _DWORD *v5; // eax
  unsigned int v6; // edx
  _DWORD *v7; // ecx
  char *v8; // edi
  unsigned int v9; // esi
  bool v10; // cf
  unsigned int i; // esi
  _BYTE *v12; // ecx
  void *v13; // ecx
  int v14; // eax
  int v16; // [esp-4h] [ebp-84h]
  int v17; // [esp-4h] [ebp-84h]
  int v18; // [esp+0h] [ebp-80h]
  int v19; // [esp+0h] [ebp-80h]
  int v20; // [esp+0h] [ebp-80h]
  _BYTE *Block; // [esp+10h] [ebp-70h]
  unsigned int v22; // [esp+24h] [ebp-5Ch]
  void *v23[5]; // [esp+28h] [ebp-58h] BYREF
  unsigned int v24; // [esp+3Ch] [ebp-44h]
  char Src[48]; // [esp+40h] [ebp-40h] BYREF
  int v26; // [esp+7Ch] [ebp-4h]

  ModuleHandleW = GetModuleHandleW(0);
  sub_402320(ModuleHandleW);
  sub_4024A0();
  v4 = sub_402870(sub_402AC0);
  std::ostream::operator<<(v4, v16);
  sub_402870(v18);
  sub_402AF0(v19);
  v23[4] = 0;
  v24 = 15;
  LOBYTE(v23[0]) = 0;
  sub_401D30(v23, Src, strlen(Src));
  v26 = 0;
  v5 = (_DWORD *)sub_4020D0(v20);
  v6 = strlen(aPvfqyc4ttc2uxr);
  v7 = v5;
  if ( v5[5] >= 0x10u )
    v7 = (_DWORD *)*v5;
  v8 = aPvfqyc4ttc2uxr;
  v9 = v5[4];
  if ( v6 < v9 )
    v9 = v6;
  v10 = v9 < 4;
  for ( i = v9 - 4; !v10; i -= 4 )
  {
    if ( *v7 != *(_DWORD *)v8 )
      break;
    ++v7;
    v8 += 4;
    v10 = i < 4;
  }
  if ( v22 >= 0x10 )
  {
    v12 = Block;
    if ( v22 + 1 >= 0x1000 )
    {
      v12 = (_BYTE *)*((_DWORD *)Block - 1);
      if ( (unsigned int)(Block - v12 - 4) > 0x1F )
        invalid_parameter_noinfo_noreturn();
    }
    sub_402F05(v12);
  }
  v26 = -1;
  if ( v24 >= 0x10 )
  {
    v13 = v23[0];
    if ( v24 + 1 >= 0x1000 )
    {
      v13 = (void *)*((_DWORD *)v23[0] - 1);
      if ( (unsigned int)(v23[0] - v13 - 4) > 0x1F )
        invalid_parameter_noinfo_noreturn();
    }
    sub_402F05(v13);
  }
  v14 = sub_402870(sub_402AC0);
  std::ostream::operator<<(v14, v17);
  system("pause");
  return 0;
}

void __thiscall sub_402320(_DWORD *this)
{
  int v1; // eax
  __int16 v2; // bx
  const char *v3; // esi
  int i; // edi
  int v5; // eax

  v1 = this[15];
  v2 = *(_WORD *)((char *)this + v1 + 6);
  v3 = (char *)this + v1 + 248;
  for ( i = 0; i < v2; ++i )
  {
    v5 = strcmp(v3, ".SCTF");
    if ( v5 )
      v5 = v5 < 0 ? -1 : 1;
    if ( !v5 )
    {
      DebugBreak();
      return;
    }
    v3 += 40;
  }
}

int sub_4024A0()
{
  unsigned int NtGlobalFlag; // [esp+10h] [ebp-20h]

  NtGlobalFlag = NtCurrentPeb()->NtGlobalFlag;
  if ( NtCurrentPeb()->BeingDebugged || NtGlobalFlag == 112 )
    exit(-5);
  return ((int (*)(void))dword_404000[0])();
}

dword_404000应该是SMC, sub_402320这个函数原来是通过调试器附加的方式来进行SMC修改, 静态分析遇到阻碍, 直接动调, 这里有个反调试, 修改EIP绕过反调, 或者nop
在这里插入图片描述
动调过程中可以拿到base64编码之后的check字符串nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=

通过findcrypt可以发现程序存在AES加密, 定位到sub_401690函数
在这里插入图片描述

int __thiscall sub_401690(int this, int a2, int a3, int a4, int a5)
{
  int v5; // ebx
  int v6; // eax
  int v7; // eax
  BOOL v8; // eax
  int v9; // ecx
  int v10; // esi
  int v11; // eax
  int v12; // ecx
  char *v13; // edx
  int v14; // edx
  char *v15; // esi
  const char *key; // esi
  int v17; // kr04_4
  _DWORD *v18; // edx
  int result; // eax
  int v20; // edi
  int v21; // ebx
  int v22; // eax
  int v23; // edx
  int v24; // ecx
  int v25; // esi
  int v26; // edi
  int v27; // eax
  int v28; // eax
  int v29; // et2
  int v30; // ecx
  int v31; // edx
  char *v32; // eax
  int v33; // ecx
  int v34; // ecx
  int v35; // edx
  int v36; // eax
  int v37; // eax
  int v38; // edx
  int v39; // ecx
  int v40; // edx
  int v41; // ecx
  int v42; // eax
  _DWORD *v43; // ecx
  __int64 v44; // rax
  __int64 v45; // rt2
  int v46; // ecx
  int *v47; // edx
  int *v48; // esi
  int v49; // edi
  int v50; // edx
  int v52; // [esp+Ch] [ebp-18h]
  int v53; // [esp+Ch] [ebp-18h]
  int v54; // [esp+10h] [ebp-14h]
  int v55; // [esp+10h] [ebp-14h]
  int v56; // [esp+14h] [ebp-10h]
  _DWORD *v57; // [esp+14h] [ebp-10h]
  _DWORD *v58; // [esp+18h] [ebp-Ch]
  char *v59; // [esp+18h] [ebp-Ch]
  int v60; // [esp+1Ch] [ebp-8h]
  int v61; // [esp+20h] [ebp-4h]

  v5 = this;
  *(_DWORD *)(this + 972) = 16;
  *(_DWORD *)(this + 968) = 16;
  *(_OWORD *)(this + 980) = xmmword_407360;
  memcpy((void *)(this + 1012), &xmmword_407360, *(_DWORD *)(this + 972));
  v6 = *(_DWORD *)(v5 + 968);
  if ( v6 == 16 )
  {
    v9 = *(_DWORD *)(v5 + 972);
    if ( v9 == 16 )
    {
      v7 = 10;
      goto LABEL_9;
    }
    v8 = v9 != 24;
  }
  else
  {
    if ( v6 != 24 )
    {
      v7 = 14;
      goto LABEL_9;
    }
    v8 = *(_DWORD *)(v5 + 972) == 32;
  }
  v7 = 2 * v8 + 12;
LABEL_9:
  *(_DWORD *)(v5 + 976) = v7;
  v10 = 0;
  v11 = *(_DWORD *)(v5 + 976);
  v12 = *(_DWORD *)(v5 + 972) / 4;
  v61 = v12;
  if ( v11 >= 0 )
  {
    v13 = (char *)(v5 + 8);
    do
    {
      if ( v12 > 0 )
      {
        memset(v13, 0, 4 * v12);
        v12 = v61;
      }
      v11 = *(_DWORD *)(v5 + 976);
      ++v10;
      v13 += 32;
    }
    while ( v10 <= v11 );
  }
  v14 = 0;
  if ( v11 >= 0 )
  {
    v15 = (char *)(v5 + 488);
    do
    {
      if ( v12 > 0 )
      {
        memset(v15, 0, 4 * v12);
        v12 = v61;
      }
      v11 = *(_DWORD *)(v5 + 976);
      ++v14;
      v15 += 32;
    }
    while ( v14 <= v11 );
  }
  key = "sycloversyclover";
  v60 = v12 * (v11 + 1);
  v17 = *(_DWORD *)(v5 + 968);
  v18 = (_DWORD *)(v5 + 1044);
  result = v17 / 4;
  v20 = v5 + 1044;
  v54 = v17 / 4;
  v56 = v5 + 1044;
  if ( v17 / 4 > 0 )
  {
    v21 = v17 / 4;
    do
    {
      v22 = *(unsigned __int8 *)key;
      key += 4;
      v22 <<= 24;
      v20 += 4;
      *(_DWORD *)(v20 - 4) = v22;
      v23 = v22 | (*((unsigned __int8 *)key - 3) << 16);
      *(_DWORD *)(v20 - 4) = v23;
      v24 = v23 | (*((unsigned __int8 *)key - 2) << 8);
      *(_DWORD *)(v20 - 4) = v24;
      result = v24 | *((unsigned __int8 *)key - 1);
      *(_DWORD *)(v20 - 4) = result;
      --v21;
    }
    while ( v21 );
    v5 = this;
    v12 = v61;
    v18 = (_DWORD *)v56;
  }
  v25 = v17 / 4;
  v26 = 0;
  if ( v54 > 0 )
  {
    v58 = v18;
    do
    {
      if ( v26 >= v60 )
        goto LABEL_44;
      v27 = v26++;
      v29 = v27 % v12;
      v28 = v27 / v12;
      *(_DWORD *)(v5 + 4 * (v29 + 8 * v28) + 8) = *v58;
      v25 = v17 / 4;
      v30 = v29 + 8 * (*(_DWORD *)(v5 + 976) - v28);
      result = *v58;
      *(_DWORD *)(v5 + 4 * v30 + 488) = *v58;
      v12 = v61;
      ++v58;
    }
    while ( v26 < v54 );
  }
  if ( v26 < v60 )
  {
    v59 = (char *)&unk_406B40;
    do
    {
      v31 = *(_DWORD *)(v5 + 4 * v25 + 1040);
      v32 = v59++;
      v33 = (unsigned __int8)RijnDael_AES_LONG_405DE0[HIBYTE(v31)] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)v31] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[BYTE1(v31)] ^ ((*v32 ^ RijnDael_AES_LONG_405DE0[BYTE2(v31)]) << 8)) << 8)) << 8);
      result = v5 + 1044;
      *(_DWORD *)(v5 + 1044) ^= v33;
      if ( v25 == 8 )
      {
        v37 = v5 + 1048;
        v38 = 3;
        do
        {
          v39 = *(_DWORD *)(v37 - 4);
          v37 += 4;
          *(_DWORD *)(v37 - 4) ^= v39;
          --v38;
        }
        while ( v38 );
        v40 = 3;
        *(_DWORD *)(v5 + 1060) ^= (unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)*(_DWORD *)(v5 + 1056)] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[BYTE1(*(_DWORD *)(v5 + 1056))] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)BYTE2(*(_DWORD *)(v5 + 1056))] ^ (RijnDael_AES_LONG_405DE0[HIBYTE(*(_DWORD *)(v5 + 1056))] << 8)) << 8)) << 8);
        v41 = v5 + 1064;
        do
        {
          v42 = *(_DWORD *)(v41 - 4);
          v41 += 4;
          *(_DWORD *)(v41 - 4) ^= v42;
          --v40;
        }
        while ( v40 );
      }
      else
      {
        if ( v25 <= 1 )
          goto LABEL_39;
        v34 = v5 + 1048;
        v35 = v25 - 1;
        do
        {
          v36 = *(_DWORD *)(v34 - 4);
          v34 += 4;
          *(_DWORD *)(v34 - 4) ^= v36;
          --v35;
        }
        while ( v35 );
      }
      result = v5 + 1044;
LABEL_39:
      v52 = 0;
      if ( v25 > 0 )
      {
        v43 = (_DWORD *)result;
        v57 = (_DWORD *)result;
        while ( v26 < v60 )
        {
          v44 = v26++;
          v45 = v44 % v61;
          LODWORD(v44) = v44 / v61;
          *(_DWORD *)(v5 + 4 * (v45 + 8 * v44) + 8) = *v43;
          v25 = v17 / 4;
          *(_DWORD *)(v5 + 4 * (v45 + 8 * (*(_DWORD *)(v5 + 976) - v44)) + 488) = *v57;
          result = v52 + 1;
          v43 = v57 + 1;
          v52 = result;
          ++v57;
          if ( result >= v54 )
            goto LABEL_43;
        }
        break;
      }
LABEL_43:
      ;
    }
    while ( v26 < v60 );
  }
LABEL_44:
  v46 = 1;
  v53 = 1;
  if ( *(int *)(v5 + 976) <= 1 )
  {
    *(_BYTE *)(v5 + 4) = 1;
  }
  else
  {
    result = v61;
    v47 = (int *)(v5 + 520);
    v55 = v5 + 520;
    do
    {
      if ( result > 0 )
      {
        v48 = v47;
        v49 = result;
        do
        {
          v50 = *v48++;
          *(v48 - 1) = dword_406B60[(unsigned __int8)v50] ^ dword_4066E0[BYTE1(v50)] ^ dword_405EE0[BYTE2(v50)] ^ dword_406F60[HIBYTE(v50)];
          --v49;
        }
        while ( v49 );
        result = v61;
        v46 = v53;
        v47 = (int *)v55;
      }
      ++v46;
      v47 += 8;
      v53 = v46;
      v55 = (int)v47;
    }
    while ( v46 < *(_DWORD *)(v5 + 976) );
    *(_BYTE *)(v5 + 4) = 1;
  }
  return result;
}

分析可以得知密钥为sycloversyclover, 偏移量为sctfsctfsctfsctf, CBC模式

from Crypto.Cipher import AES  
from base64 import b64decode, b64encode


BLOCK_SIZE = AES.block_size
pad = lambda s: s + (BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

class AESCipher:
    def __init__(self):
        self.key = 'sycloversyclover'
        self.iv = 'sctfsctfsctfsctf'
 
    def encrypt(self, text):
        text = pad(text).encode()  
        cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
        encrypted_text = cipher.encrypt(text)
        return b64encode(encrypted_text).decode('utf-8')
 
    def decrypt(self, encrypted_text):
        encrypted_text = b64decode(encrypted_text)
        cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
        decrypted_text = cipher.decrypt(encrypted_text)
        return unpad(decrypted_text).decode('utf-8')


if __name__ == '__main__':
    AESobj = AESCipher()
    flag = AESobj.decrypt('nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=')
    print(flag)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值