2021东华杯-Re-All

2021东华杯-Re-all

对于这个比赛呢,还是挺有感悟的,你一个人怎么和那些"几个队伍一起打的"对线,我也不知道该怎么说,我只能说打ctf的都懂我前面那句话,虽然我花了一天AK了逆向,但是也没用,hh…

看题吧,还是有些地方能够积累一些经验的

ooo

这道题应该算是一道签到题吧

在这里插入图片描述

看汇编

movzx   edx, byte ptr [rbp-105]
movzx   eax, byte ptr [rbp-104]
xor     edx, eax
movzx   eax, byte ptr [rbp-103]
xor     eax, edx
mov     [rbp-75h], al

取了flag中间的三个字节来异或得到一个值

然后将flag的所有字节都异或这个值

然后这个xor_data数据类型是char的,直接爆破255范围即可

cmp = [0x00000011, 0x0000011B, 0x00000216, 0x00000310, 0x0000040C, 0x00000546, 0x00000644, 0x00000711, 0x00000844, 0x00000942, 0x00000A41, 0x00000B41, 0x00000C44, 0x00000D5A, 0x00000E42, 0x00000F47, 0x00001016, 0x00001143, 0x0000125A, 0x00001343, 0x00001440, 0x00001540, 0x00001615, 0x0000175A, 0x00001845, 0x00001940, 0x00001A4F, 0x00001B15, 0x00001C5A, 0x00001D15, 0x00001E40, 0x00001F46, 0x00002046, 0x00002147, 0x00002245, 0x00002341, 0x00002411, 0x00002511, 0x00002640, 0x00002716, 0x00002813, 0x0000290A]

def all_see(arr):
    cnt = 0
    for k in range(len(arr)):
        if (arr[k] > 32) and (arr[k] < 127):
            cnt += 1
    if cnt == len(arr):
        return True
    else:
        return False

for i in range(255):
    temp = []
    for j in range(len(cmp)):
        temp.append((cmp[j] ^ i) & 0xff)
    if all_see(temp):
        for m in range(len(temp)):
            print(chr(temp[m]), end='')
        print()
# test.py
1;60,fd1dbaadzbg6czc``5ze`o5z5`ffgea11`63*
0:71-ge0ec``e{cf7b{baa4{dan4{4aggfd`00a72+
3942.df3f`ccfx`e4axabb7xgbm7x7bddegc33b41(
2853/eg2gabbgyad5`y`cc6yfcl6y6ceedfb22c50)
5?24(b`5`fee`~fc2g~gdd1~adk1~1dbbcae55d27.
7=06*`b7bdggb|da0e|eff3|cfi3|3f``acg77f05,
6<17+ac6ceffc}e`1d}dgg2}bgh2}2gaa`bf66g14-
93>8$nl9ljiilrjo>krkhh=rmhg=r=hnnomi99h>;"
82?9%om8mkhhmskn?jsjii<slif<s<ioonlh88i?:#
:0=;'mo:oijjoqil=hqhkk>qnkd>q>kmmlnj::k=8!
<6;=!ki<iolliwoj;nwnmm8whmb8w8mkkjhl<<m;>'
?58>"hj?jloojtli8mtmnn;tkna;t;nhhiko??n8=$
>49?#ik>kmnnkumh9luloo:ujo`:u:oiihjn>>o9<%
#)$">tv#vpssvhpu$qhqrr'hwr}'h'rttuws##r$!8
%/"$8rp%pvuupnvs"wnwtt!nqt{!n!trrsqu%%t"'>
&,!';qs&suvvsmup!tmtww"mrwx"m"wqqprv&&w!$=
ys~xd.,y,*)),2*/~+2+((}2-('}2}(../-)yy(~{b
zp}{g-/z/)**/1),}(1(++~1.+$~1~+--,.*zz+}xa
|v{}a+)|)/,,)7/*{.7.--x7(-"x7x-++*(,||-{~g
akf`|64a42114*27f3*300e*50?e*e066751aa0fcz
`jga}75`53005+36g2+211d+41>d+d177640``1gb{
cidb~46c60336(05d1(122g(72=g(g244573cc2dax
eobdx20e06550.63b7.744a.14;a.a422315ee4bg~
gm`fz02g24772,41`5,566c,369c,c600137gg6`e|
flag{13f35663-50a4-477b-278b-b711026ff7ad}
icnht><i<:99<":?n;";88m"=87m"m8>>?=9ii8nkr
hboiu?=h=;88=#;>o:#:99l#<96l#l9??><8hh9ojs
j`mkw=?j?9::?!9<m8!8;;n!>;4n!n;==<>:jj;mhq
mgjlp:8m8>==8&>;j?&?<<i&9<3i&i<::;9=mm<jov
lfkmq;9l9?<<9'?:k>'>==h'8=2h'h=;;:8<ll=knw
oehnr8:o:<??:$<9h=$=>>k$;>1k$k>889;?oo>hmt
ndios9;n;=>>;%=8i<%<??j%:?0j%j?998:>nn?ilu

Process finished with exit code 0

mod

有一些花指令导致ida反编译失败,修改修改

int __cdecl sub_401320(int a1)
{
  int result; // eax
  char v2; // [esp+0h] [ebp-3Ch]
  char *v3; // [esp+10h] [ebp-2Ch]
  char *Buffer; // [esp+14h] [ebp-28h]
  signed int v5; // [esp+1Ch] [ebp-20h]
  int i; // [esp+28h] [ebp-14h]

  v5 = strlen(byte_4054A8);
  length = v5;
  if ( v5 % 3 == 1 )
  {
    Buffer = &byte_4054A8[length++];
    sub_401020(Buffer, "=", v2);
  }
  else if ( v5 % 3 != 2 )
  {
    goto LABEL_6;
  }
  v3 = &byte_4054A8[length++];
  sub_401020(v3, "=", v2);
LABEL_6:
  for ( i = 0; i < length; i += 3 )
    main_encrypt(byte_4054A8, i, a1);
  result = v5 / 3;
  if ( v5 % 3 == 1 )
    return sub_401020((a1 + 4 * (v5 / 3)), "==", v2);
  if ( v5 % 3 == 2 )
    return sub_401020((a1 + 4 * (v5 / 3)), "=", v2);
  return result;
}
int __cdecl main_encrypt(char *a1, int a2, char *a3)
{
  int result; // eax
  _BYTE v4[64]; // [esp+Ch] [ebp-40h] BYREF

  memset(v4, 0xCCu, sizeof(v4));
  a3[4 * (a2 / 3)] = aAbcdfegh1jklrs[((4 * (a1[a2 + 2] & 3)) | a1[a2 + 1] & 0x30 | a1[a2] & 0xC0) >> 2];
  a3[4 * (a2 / 3) + 1] = aAbcdfegh1jklrs[((4 * (a1[a2] & 3)) | a1[a2 + 2] & 0x30 | a1[a2 + 1] & 0xC0) >> 2];
  a3[4 * (a2 / 3) + 2] = aAbcdfegh1jklrs[((4 * (a1[a2 + 1] & 3)) | a1[a2] & 0x30 | a1[a2 + 2] & 0xC0) >> 2];
  result = a2 / 3;
  a3[4 * (a2 / 3) + 3] = aAbcdfegh1jklrs[(a1[a2 + 2] & 0xC | (4 * a1[a2 + 1]) & 0x30 | (16 * a1[a2]) & 0xC0) >> 2];
  return result;
}

可以得到就是一个base64,但是是不可逆的

使用z3来求解

# _*_ coding: utf-8 _*_
# editor: SYJ
# function: Reversed By SYJ
"""
describe:

"""
import base64
changed = "ABCDFEGH1JKLRSTMNP0VWQUXY2a8cdefijklmnopghwxyqrstuvzOIZ34567b9+/"
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
inp = b"0123456789abcdef=="
for i in range(0, len(inp), 3):
    print(changed[((4 * (inp[i + 2] & 3)) | inp[i + 1] & 0x30 | inp[i] & 0xc0) >> 2], end='')
    print(changed[((4 * (inp[i] & 3)) | inp[i + 2] & 0x30 | inp[i + 1] & 0xC0) >> 2], end='')
    print(changed[((4 * (inp[i + 1] & 3)) | inp[i] & 0x30 | inp[i + 2] & 0xC0) >> 2], end='')
    print(changed[(inp[i + 2] & 0xC | (4 * inp[i + 1]) & 0x30 | (16 * inp[i]) & 0xC0) >> 2], end='')
# 上面是试试加密是否对拍正确
print()

# 下面使用z3求解
from z3 import *
enflag = '2aYcdfL2fS1BTMMF1RSeMTTASS1OJ8RHTJdBYJ2STJfNMSMAYcKUJddp'
for i in range(0, len(enflag), 4):
    flag_part = [BitVec(('x%d' % j), 8) for j in range(3)]
    s = Solver()
    for k in range(0, 3):
        s.add(flag_part[k] < 127)
        s.add(flag_part[k] > 32)
    s.add(((4 * (flag_part[2] & 3)) | flag_part[1] & 0x30 | flag_part[0] & 0xc0) == changed.find(enflag[i]) << 2)
    s.add(((4 * (flag_part[0] & 3)) | flag_part[2] & 0x30 | flag_part[1] & 0xC0) == changed.find(enflag[i+1]) << 2)
    s.add(((4 * (flag_part[1] & 3)) | flag_part[0] & 0x30 | flag_part[2] & 0xC0) == changed.find(enflag[i+2]) << 2)
    s.add((flag_part[2] & 0xC | (4 * flag_part[1]) & 0x30 | (16 * flag_part[0]) & 0xC0) == changed.find(enflag[i+3]) << 2)
    if s.check() == sat:
        model = s.model()
        b = [chr(model[flag_part[m]].as_long().real) for m in range(3)]
        flag_ = "".join(b)
        print(flag_, end='')
    else:
        print("sorry!!!!!unsat!!!")
flag{5a073724-8223-413d-11fa-d53b133df89e}

hello

一道apk,先看静态

关键逻辑

在这里插入图片描述

public native String stringFromJNI(String str, String str2);
stringFromJNI(MainActivity.this.input.getText().toString(), new C0374hi().getSignatures(view))

第一个参数是我们输入的字符串,第二个参数是获取的包的签名信息

解包后查看so文件

jstring __fastcall Java_com_example_hello_MainActivity_stringFromJNI(_JNIEnv *a1, __int64 a2, __int64 a3, __int64 a4)
{
  int8x16_t *inp; // x20
  const char *sign; // x0
  const char *v8; // x21
  unsigned __int64 i; // x23
  unsigned int j; // w24
  unsigned int v11; // w1
  unsigned __int8 v12; // w9
  unsigned int v13; // w11
  unsigned int v14; // w12
  unsigned int v15; // w13
  unsigned int v16; // w14
  unsigned int v17; // w15
  int8x16_t v18; // q0
  unsigned int v19; // w16
  int8x16_t v20; // q1
  unsigned int v21; // w17
  __int64 k; // x8
  const char *v23; // x21
  jstring v24; // x19
  char v26[16]; // [xsp+0h] [xbp-50h] BYREF
  const char *v27; // [xsp+10h] [xbp-40h]
  __int64 v28; // [xsp+18h] [xbp-38h]

  v28 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  inp = (int8x16_t *)a1->functions->GetStringUTFChars(a1, a3, 0LL);
  sign = a1->functions->GetStringUTFChars(a1, a4, 0LL);
  if ( inp->n128_u8[0] )
  {
    v8 = sign;
    inp->n128_u8[0] ^= sign[327];               // 0x66 ^ 0x30
    if ( strlen((const char *)inp) >= 2uLL )
    {
      i = 1LL;
      j = 354;
      do
      {
        inp->n128_u8[i] ^= v8[j] + (_BYTE)i;    // 异或回去即可
        ++i;
        j += 27;
      }
      while ( strlen((const char *)inp) > i );
    }
  }
  v11 = (inp[2].n128_u8[0] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[0]);
  v12 = (inp[2].n128_u8[1] >> 3) & 31 | (32 * inp[2].n128_u8[1]);
  v13 = (inp[2].n128_u8[3] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[3]);
  v14 = (inp[2].n128_u8[4] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[4]);
  v15 = (inp[2].n128_u8[5] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[5]);
  v16 = (inp[2].n128_u8[6] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[6]);
  v17 = (inp[2].n128_u8[7] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[7]);
  v18 = vorrq_s8(vshrq_n_u8(*inp, 3uLL), vshlq_n_s8(*inp, 5uLL));
  v19 = (inp[2].n128_u8[8] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[8]);
  v20 = vorrq_s8(vshrq_n_u8(inp[1], 3uLL), vshlq_n_s8(inp[1], 5uLL));
  v21 = (inp[2].n128_u8[9] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[9]);
  inp[2].n128_u8[2] = (inp[2].n128_u8[2] >> 3) & 0x1F | (32 * inp[2].n128_u8[2]);
  inp[2].n128_u8[0] = v11;
  inp[2].n128_u8[1] = v12;
  inp[2].n128_u8[3] = v13;
  inp[2].n128_u8[4] = v14;
  inp[2].n128_u8[5] = v15;
  inp[2].n128_u8[6] = v16;
  inp[2].n128_u8[7] = v17;
  inp[2].n128_u8[8] = v19;
  inp[2].n128_u8[9] = v21;
  *inp = v18;
  inp[1] = v20;
  v26[15] = 0;
  v26[0] = 26;
  k = 0LL;
  v27 = 0LL;
  v23 = &v26[1];
  strcpy(&v26[1], "Wrong, wrong!");
  while ( inp->n128_u8[k] == byte_6F75D41460[k] )
  {
    if ( (unsigned __int64)++k > 0x29 )
    {
      std::string::assign(v26, "Hello, hello!", 13LL);
      if ( (v26[0] & 1) != 0 )
        v23 = v27;
      break;
    }
  }
  v24 = a1->functions->NewStringUTF(a1, v23);
  if ( (v26[0] & 1) != 0 )
    operator delete(v27);
  return v24;
}

先和包的签名信息异或之后进行了位运算

然后想方法获取包的签名信息

在安装apk的时候报错

看了下AndroidManifest.xml

android:testOnly="true" 这个标记原本是用来标记测试用的,所以带这个标记的包一般情况下是不能安装上的

本想修改一下这个为false,然后重新打包,但是在签名的时候会改掉它原来的签名

然后进行了资料查找之后

-t测试package标志
adb install -t test.apk #allow test packages

然后就安装上了,直接调试获取到签名

解题脚本:

crt是我们提取的签名数据

crt

date = open(r'D:\CTF\COMPETITIONS\2021dhb\Re\hello\crt', 'rb').read()
good = []
for i in range(42):
    for j in range(0xff):
        if ((j >> 3) & 0xFFFFE01F | (j << 5)) & 0xff == cmp[i]:
            good.append(j)
for i in range(42):
    # print(hex(temp[i] ^ (date[327+i*27] + i)), end=', ')
    print(chr((good[i] ^ (date[327+i*27] + i))), end='')
flag{d5577edd-8211-7a0e-f23a-305b0b10683f}

HellsGate

一道32位程序调用了64位程序的

参考资料:https://www.anquanke.com/post/id/171111

如果此时栈中有0x33,则会将0x33弹出到CS寄存器中,实现32位程序切换到64位代码的过程。所以retf是识别32位程序调用64位代码的重要标志。

LONG __stdcall Handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
  HANDLE CurrentProcess; // eax
  NTSTATUS (__stdcall *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); // [esp+10h] [ebp-10h]
  HMODULE hModule; // [esp+14h] [ebp-Ch]
  int dwDebugport; // [esp+18h] [ebp-8h] BYREF

  if ( ExceptionInfo->ContextRecord->Eip != &loc_416DFF )
    return 0;
  hModule = LoadLibraryA(LibFileName);          // ntdll.dll
  if ( !hModule )
    _loaddll(0);
  NtQueryInformationProcess = GetProcAddress(hModule, aNtqueryinforma);
  if ( !NtQueryInformationProcess )             // NtQueryInformationProcess
    _loaddll(0);
  dwDebugport = 0;
  CurrentProcess = GetCurrentProcess();
  if ( (NtQueryInformationProcess)(CurrentProcess, 7, &dwDebugport, 4, 0) || !dwDebugport )// 调试处于0xffffffff, 非调试处于0
  {
    sub_4174C0(*(ExceptionInfo->ContextRecord->Ebp + 8));// 非调试进入该函数
    return _loaddll(0);
  }
  else
  {
    ExceptionInfo->ContextRecord->Eax = ExceptionInfo->ContextRecord->Eax;
    ExceptionInfo->ContextRecord->Ecx = ExceptionInfo->ContextRecord->Ecx;
    return -1;
  }
}

关键逻辑在sub_4174C0中

在这里插入图片描述

有许多小函数,进小函数之后就反编译失败,全是JUMPOUT

查看汇编

在这里插入图片描述

32位调用64位的特征

说明后面那些机器码是64位的

我们直接PE文件头中标识程序为32位的修改为64然后拖入ida

类似如下:

void __fastcall __noreturn sub_41730F(int a1, int a2)
{
  void *retaddr[2]; // [rsp+0h] [rbp+0h]

  LODWORD(retaddr[1]) = a1;
  dword_420400[a1] = *(_DWORD *)(unsigned int)(a2 + dword_4203E0);
}

就可以知道这个函数做了什么

然后全部

BOOL __cdecl sub_4174C0(void *lpBuffer)
{
  HANDLE StdHandle; // eax
  BOOL result; // eax
  HANDLE v3; // eax
  HANDLE v4; // eax
  HANDLE v5; // eax
  HANDLE v6; // eax
  HANDLE v7; // eax
  HANDLE v8; // eax
  HANDLE v9; // eax
  HANDLE v10; // eax
  HANDLE v11; // eax
  HANDLE v12; // eax
  HANDLE v13; // eax
  int v14; // [esp-78h] [ebp-94h]
  int v15; // [esp-68h] [ebp-84h]
  int v16; // [esp-54h] [ebp-70h]
  int v17; // [esp-48h] [ebp-64h]
  int v18; // [esp-40h] [ebp-5Ch]
  int v19; // [esp-38h] [ebp-54h]
  int v20; // [esp-34h] [ebp-50h]
  int v21; // [esp-30h] [ebp-4Ch]
  int v22; // [esp-28h] [ebp-44h]
  int v23; // [esp-14h] [ebp-30h]
  int v24; // [esp-8h] [ebp-24h]
  int k; // [esp+0h] [ebp-1Ch]
  int v26; // [esp+0h] [ebp-1Ch]
  int m; // [esp+4h] [ebp-18h]
  int i; // [esp+8h] [ebp-14h]
  int j; // [esp+Ch] [ebp-10h]
  __int64 Buffer; // [esp+10h] [ebp-Ch] BYREF
  int v31; // [esp+18h] [ebp-4h]

  sub_4173E0();
  for ( i = 0; i < 32; ++i )
    *(i + dword_4203E0) = *(lpBuffer + i);
  (sub_4171B0)(0, 0x12345678);                  // dword_420400[0] = 0x12345678
  (sub_4171B0)(1, 0x87654321);                  // dword_420400[a1] = a2
  (sub_4171B0)(2, 0x13243546);
  (sub_4171B0)(3, 0x64534231);
  sub_417370();                                 // *(a1 + dword_4203E0) = dword_420400[a2]
  sub_417370();                                 // dword_4203E0内存开始的32 40 48 56 64存放了这5个值
  sub_417370();
  sub_417370();
  (sub_4171B0)(0, 0xB879379E);
  sub_417370();
  for ( j = 0; j < 32; j += 8 )
  {
    sub_417300();                               // dword_420400[0] = *(32 + dword_4203E0)
    sub_417300();                               // dword_420400[1] = *(36 + dword_4203E0)
    sub_417370();                               // *(72 + dword_4203E0) = dword_420400[0]
    sub_417370();                               // *(80 + dword_4203E0) = dword_420400[1]
    (sub_4171B0)(0, 0, v14);                    // dword_420400[0] = 0
    sub_417370();                               // *(88 + dword_4203E0) = dword_420400[0]
    for ( k = 0; k < 16; k = v26 + 1 )
    {
      sub_417300();                             // dword_420400[0] = *(88 + dword_4203E0)
      sub_417300();                             // dword_420400[1] = *(64 + dword_4203E0)
      (sub_417290)(0, 1, v15);                  // dword_420400[0] += dword_420400[1]
      sub_417370();                             // *(88 + dword_4203E0) = dword_420400[0]
      sub_417300();                             // dword_420400[0] = *(80 + dword_4203E0)
      sub_417140();                             // dword_420400[0] <<= 4
      sub_417300();                             // dword_420400[1] = *(32 + dword_4203E0)
      (sub_417290)(0, 1, v16);                  // dword_420400[0] += dword_420400[1]
      sub_417300();                             // dword_420400[1] = *(80 + dword_4203E0)
      sub_417300();                             // dword_420400[2] = *(88 + dword_4203E0)
      (sub_417290)(1, 2, v17);                  // dword_420400[1] += dword_420400[2]
      sub_417300();                             // dword_420400[2] = *(80 + dword_4203E0)
      (sub_4170D0)(2, 5, v18);                  // dword_420400[2] >>= 5
      sub_417300();                             // dword_420400[3] = *(40 + dword_4203E0)
      (sub_417290)(2, 3, v19);                  // dword_420400[2] += dword_420400[3]
      (sub_417220)(1, 2, v20);                  // dword_420400[1] ^= dword_420400[2]
      (sub_417220)(0, 1, v21);                  // dword_420400[0] ^= dword_420400[1]
      sub_417300();                             // dword_420400[1] = *(72 + dword_4203E0)
      (sub_417290)(1, 0, v22);                  // dword_420400[1] += dword_420400[0]
      sub_417370();                             // *(72 + dword_4203E0) = dword_420400[1]
      sub_417300();                             // dword_420400[0] = *(72 + dword_4203E0)
      sub_417140();                             // dword_420400[0] <<= 4
      sub_417300();                             // dword_420400[1] = *(48 + dword_4203E0)
      (sub_417290)(0, 1, v23);                  // dword_420400[0] += dword_420400[1]
      sub_417300();                             // dword_420400[1] = *(72 + dword_4203E0)
      sub_417300();                             // dword_420400[2] = *(88 + dword_4203E0)
      (sub_417290)(1, 2, v24);                  // dword_420400[1] += dword_420400[2]
      sub_417300();                             // dword_420400[2] = *(72 + dword_4203E0)
      (sub_4170D0)(2, 5, k);                    // dword_420400[2] >>= 5
      sub_417300();                             // dword_420400[3] = *(56 + dword_4203E0)
      (sub_417290)(2, 3, i);                    // dword_420400[2] += dword_420400[3]
      (sub_417220)(1, 2, j);                    // dword_420400[1] ^= dword_420400[2]
      (sub_417220)(0, 1, Buffer);               // dword_420400[0] ^= dword_420400[1]
      sub_417300();                             // dword_420400[1] = *(80 + dword_4203E0)
      (sub_417290)(1, 0, v31);                  // dword_420400[1] += dword_420400[0]
      sub_417370();                             // *(80 + dword_4203E0) = dword_420400[1]
    }
    sub_417300();                               // dword_420400[0] = *(72 + dword_4203E0)
    sub_417300();                               // dword_420400[1] = *(80 + dword_4203E0)
    sub_417370();                               // *(j + dword_4203E0) = dword_420400[0]
    sub_417370();                               // *(j+4 + dword_4203E0) = dword_420400[1]
                                                // *(_DWORD *)(unsigned int)(a1 + dword_4203E0) = dword_420400[a2]
  }
  strcpy(&Buffer, "right\n");
  HIBYTE(Buffer) = 0;
  for ( m = 0; m < 32; ++m )
  {
    if ( *(m + dword_4203E0) != *(off_41F8D4 + m) )
    {
      strcpy(&Buffer, "wrong\n");
      HIBYTE(Buffer) = 0;
      break;
    }
  }
  StdHandle = GetStdHandle(0xFFFFFFF5);
  result = WriteConsoleA(StdHandle, &Buffer, 6u, 0, 0);
  if ( Buffer == '\nthgir' )
  {
    Buffer = '{galf';
    v3 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v3, &Buffer, 6u, 0, 0);
    v4 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v4, lpBuffer, 8u, 0, 0);
    v5 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v5, asc_41F9A4, 1u, 0, 0);
    v6 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v6, lpBuffer + 8, 4u, 0, 0);
    v7 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v7, asc_41F9A0, 1u, 0, 0);
    v8 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v8, lpBuffer + 12, 4u, 0, 0);
    v9 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v9, asc_41F99C, 1u, 0, 0);
    v10 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v10, lpBuffer + 16, 4u, 0, 0);
    v11 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v11, asc_41F998, 1u, 0, 0);
    v12 = GetStdHandle(0xFFFFFFF5);
    WriteConsoleA(v12, lpBuffer + 20, 0xCu, 0, 0);
    v13 = GetStdHandle(0xFFFFFFF5);
    return WriteConsoleA(v13, asc_41F994, 1u, 0, 0);
  }
  return result;
}

可以得到关键的加密逻辑

解题脚本:

#include <stdio.h>
#include <stdint.h>

void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t delta=0xB879379E;
    uint32_t v0=v[0], v1=v[1], sum=(delta*16)&0xffffffff, i;
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
    for (i=0; i<16; 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()
{
    uint32_t array[] = {0x2C94650B, 0x78494E9E, 0xE7FACF44, 0x48F9DBFB, 0x547BB145, 0x925D2542, 0x69A9F4C4, 0x9A96A1D8};
    uint32_t key[4] = {0x12345678,0x87654321,0x13243546,0x64534231};
    int i = 0;
    for(i=0;i<8;i+=2)
    {
        uint32_t temp[2];
        temp[0] = array[i];
        temp[1] = array[i+1];
        decrypt(temp, key);
        //printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+3),*((char*)&temp[0]+2),*((char*)&temp[0]+1),*((char*)&temp[0]+0),*((char*)&temp[1]+3),*((char*)&temp[1]+2),*((char*)&temp[1]+1),*((char*)&temp[1]+0));
        printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+0),*((char*)&temp[0]+1),*((char*)&temp[0]+2),*((char*)&temp[0]+3),*((char*)&temp[1]+0),*((char*)&temp[1]+1),*((char*)&temp[1]+2),*((char*)&temp[1]+3));
    }

    return 0;
}
flag{0f4d0db3668dd58cabb9eb409657eaa8}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值