Reverse Engineering

ChallengeLink

Paranoia (100 pts)

Grip (100 pts)

Sperm Rev (100 pts)

Risks (205 pts)

Packeta (460 pts)

Mips (477 pts)

Orgalorg (498 pts)

Paranoia (100 pts)

Description

im baby

Author: miyako

nc 20.80.240.190 1234

Solution

Given ELF 64 bit file, open it using IDA.

int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  int v4; // ebx
  int v5; // eax
  unsigned __int64 i; // [rsp+8h] [rbp-18h]

  v3 = time(0LL);
  srand(v3);
  for ( i = 0LL; i <= 0x11; ++i )
  {
    v4 = flag[i];
    v5 = rand();
    printf("%i ", v4 ^ ((unsigned __int8)(((unsigned int)(v5 >> 31) >> 24) + v5) - ((unsigned int)(v5 >> 31) >> 24)));
  }
  putchar(10);
  return 0;

Basically it just do xor with random value with seed current time (time(0)). To get the plaintext we can do the same process. To overcome delay issue, we can do little bruteforce from current time.

from ctypes import CDLL
import time
from pwn import *

libc = CDLL("libc.so.6")
current = int(time.time())
r = remote("20.80.240.190", 1234)
ct = list(map(int, r.recvline().strip().split(b" ")))
for i in range(current, current-10, -1):
	libc.srand(i)
	tmp_flag = b""
	for v4 in ct:
		v5 = libc.rand()
		tmp_flag += bytes([v4 ^ (((((v5 >> 31) >> 24) + v5) - ((v5 >> 31) >> 24)) & 0xff)])
	print(i, tmp_flag)
r.interactive()

Flag: akasec{n0t_t00_m4ny_br41nc3lls_l3ft}

Grip (100 pts)

Description

its...its...Grippy

Author: miyako

Solution

Given ELF 64 bit, open it using IDA.

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v3; // rbx
  __int64 v4; // rbx
  __int64 v5; // rbx
  __int64 v6; // rbx
  __int64 v7; // rbx
  __int64 v8; // rbx
  __int64 v9; // rbx
  __int64 v10; // rbx
  __int64 v11; // rbx
  unsigned __int64 i; // [rsp+18h] [rbp-C8h]
  _QWORD *v14; // [rsp+20h] [rbp-C0h]
  __int64 v15; // [rsp+30h] [rbp-B0h]
  __int64 v16; // [rsp+38h] [rbp-A8h]
  __int64 v17; // [rsp+40h] [rbp-A0h]
  __int64 v18; // [rsp+48h] [rbp-98h]
  __int64 v19; // [rsp+50h] [rbp-90h]
  __int64 v20; // [rsp+58h] [rbp-88h]
  __int64 v21; // [rsp+60h] [rbp-80h]
  __int64 v22; // [rsp+68h] [rbp-78h]
  __int64 v23; // [rsp+70h] [rbp-70h]
  __int64 v24; // [rsp+78h] [rbp-68h]
  __int64 v25; // [rsp+80h] [rbp-60h]
  __int64 v26; // [rsp+88h] [rbp-58h]
  __int64 v27; // [rsp+90h] [rbp-50h]
  __int64 v28; // [rsp+98h] [rbp-48h]
  __int64 v29; // [rsp+A0h] [rbp-40h]
  char v30[13]; // [rsp+A8h] [rbp-38h]
  __int64 v31; // [rsp+B5h] [rbp-2Bh]
  unsigned __int64 v32; // [rsp+C8h] [rbp-18h]

  v32 = __readfsqword(0x28u);
  v15 = 0xB21E71BA177BBAA7LL;
  v16 = 0xF2F2DAD7F679BA96LL;
  v17 = 0xBA32C30AB77BBAF2LL;
  v18 = 0xCBD3D5C3D1DBD14ALL;
  v19 = 0xC9C4C481D848BAC3LL;
  v20 = 0xBA22B77BBA84C0EFLL;
  v21 = 0xC0EFC94ABA2AA77BLL;
  v22 = 0xEF48BAD483DBD384LL;
  v23 = 0xBACDC9C284DE81D2LL;
  v24 = 0x3516A77BBA2EB77BLL;
  v25 = 0xEA19F2F2F2F23EB7LL;
  v26 = 0x22F7B644FD3EB779LL;
  v27 = 0x3EB779307BB00271LL;
  v28 = 0xF33EB77122F7A67ALL;
  v29 = 0xBA621084E93E8F71LL;
  *(_QWORD *)v30 = 0xD7F6D9BA960AB779LL;
  *(_QWORD *)&v30[5] = 0x86F2F2F2DAD7F6D9LL;
  v31 = 0x313BF2F2F2F21AF7LL;
  for ( i = 0LL; i <= 0x8C; ++i )
    *((_BYTE *)&v15 + i) ^= 0xF2u;
  v14 = mmap(0LL, 0x8DuLL, 6, 34, -1, 0LL);
  v3 = v16;
  *v14 = v15;
  v14[1] = v3;
  v4 = v18;
  v14[2] = v17;
  v14[3] = v4;
  v5 = v20;
  v14[4] = v19;
  v14[5] = v5;
  v6 = v22;
  v14[6] = v21;
  v14[7] = v6;
  v7 = v24;
  v14[8] = v23;
  v14[9] = v7;
  v8 = v26;
  v14[10] = v25;
  v14[11] = v8;
  v9 = v28;
  v14[12] = v27;
  v14[13] = v9;
  v10 = *(_QWORD *)v30;
  v14[14] = v29;
  v14[15] = v10;
  v11 = v31;
  *(_QWORD *)((char *)v14 + 125) = *(_QWORD *)&v30[5];
  *(_QWORD *)((char *)v14 + 133) = v11;
  ((void (__fastcall *)(_QWORD))v14)(0LL);
  puts(":3");
  return 0LL;
}

We can see that there is mmap function called then the address from mmap (v14) used to store value of static value xored with 0xf2. At the end, v14 called in the main function. From those information we can assume that value on address v14 contains valid assembly because it called in the end. So dump the bytecode then open it again using decompiler.

from Crypto.Util.number import *
ct = []
ct.append(0xB21E71BA177BBAA7)
ct.append(0xF2F2DAD7F679BA96)
ct.append(0xBA32C30AB77BBAF2)
ct.append(0xCBD3D5C3D1DBD14A)
ct.append(0xC9C4C481D848BAC3)
ct.append(0xBA22B77BBA84C0EF)
ct.append(0xC0EFC94ABA2AA77B)
ct.append(0xEF48BAD483DBD384)
ct.append(0xBACDC9C284DE81D2)
ct.append(0x3516A77BBA2EB77B)
ct.append(0xEA19F2F2F2F23EB7)
ct.append(0x22F7B644FD3EB779)
ct.append(0x3EB779307BB00271)
ct.append(0xF33EB77122F7A67A)
ct.append(0xBA621084E93E8F71)
ct.append(0xD7F6D9BA960AB779)
ct.append(0x86F2F2F2DAD7F6D9)

pt = []
for i in ct:
    tmp = long_to_bytes(i)[::-1]
    for j in tmp:

        pt.append(j ^ 0xf2)
pt[-4] = 0xc3

out = open("dump.bin", "wb")
out.write(bytes(pt))

3 null bytes at the end will cause error on decompile process, so put 0xc3 (ret) to overcome the issue.

unsigned __int64 sub_0()
{
  unsigned int i; // [rsp+Ch] [rbp-34h]
  __int64 v2; // [rsp+10h] [rbp-30h]
  _DWORD v3[3]; // [rsp+18h] [rbp-28h]
  __int64 v4; // [rsp+24h] [rbp-1Ch]
  unsigned __int64 v5; // [rsp+38h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v2 = 0x3139212731232923i64;
  v3[0] = 909538090;
  *(_QWORD *)&v3[1] = 0x2671292176321D3Bi64;
  v4 = 0x3F3B30762C73201Di64;
  for ( i = 0; i <= 0x1B; ++i )
    *((_BYTE *)&v3[-2] + i) ^= 0x42u;
  return v5 - __readfsqword(0x2825042Bu);
}

Now we have the code, then just convert it to python and get the flag.

from Crypto.Util.number import *

ct = []
ct.append(0x3139212731232923)
ct.append(0x3636732A)
ct.append(0x2671292176321D3B)
ct.append(0x3F3B30762C73201D)

flag = b""
for i in ct:
  tmp = long_to_bytes(i)[::-1]
  for j in tmp:
    flag += bytes([j ^ 0x42])
print(flag)

Flag: akasec{sh1tty_p4ck3d_b1n4ry}

Sperm Rev (100 pts)

Description

before baby rev, there was sperm rev <3

solve it fast to win another race in your life.

Author: Pengolian

Solution

Given ELF 64 bit, open it using IDA. Nothing useful in available function, check on strings.

Flag: AKASEC{strings_b35t_t00l_1n_r3v3r5e_eng1n33r1ng}

Risks (205 pts)

Description

theres this pretty cool isa called riscv it sounds awesome.

Author: miyako

Solution

Given ELF 64 bit RISCV file, open it using ghidra. Rename some known function to make it easily to understand.

undefined8 main(void)

{
  char cVar1;
  long lVar2;
  undefined8 local_30;
  long local_28;
  long local_20;
  long local_18;
  
  local_28 = 0;
  local_30 = 0;
  printf_("whats the flag: ");
  local_18 = getline_(&local_28,&local_30,_stdin);
  *(local_18 + -1 + local_28) = 0;
  local_20 = local_28;
  FUN_00101ad4(local_28);
  FUN_00101346(local_20);
  FUN_00100c8c(local_20);
  FUN_00100786(local_20);
  lVar2 = strlen_(local_28);
  if ((lVar2 == 0x20) && (cVar1 = compare_value(local_20), cVar1 == '\x01')) {
    puts_("good job!");
    return 0;
  }
  puts_("nuh uh");
  return 0;
}

So there are 5 custom functions in the program.

  • FUN_00101ad4, FUN_00101346, FUN_00100c8c, and FUN_00100786 process our input with some operation such as xor and add.

  • compare_value validate our processed input with static value

From those informations we can get the valid input by utilizing z3. Below is my solution

from z3 import *
from Crypto.Util.number import *

inp = [BitVec("x{}".format(i), 64) for i in range(4)]
s = Solver()

param_1 = [0 for _ in range(4)]

# FUN_00101ad4
param_1[0] = inp[0] + 0x75978f47ac76cf;
param_1[1] = inp[1] + 0xff889b2d229768ef;
param_1[0] = param_1[0] ^ 0x76bf86ade5d5cc;
param_1[2] = inp[2] + 0x760f38b4bc69dc;
param_1[0] = param_1[0] ^ 0x559f46365cee21;
param_1[0] = param_1[0] + 0x5c6476bf0d4a19;
param_1[0] = param_1[0] ^ 0xed41cda9780;
param_1[2] = param_1[2] ^ 0x1e555c027a4e43;
param_1[3] = inp[3] + 0xfff29f96915a6e96;
param_1[0] = param_1[0] ^ 0x4c46c321e8dc3d;
param_1[2] = param_1[2] + 0x440d7b5dafb63c;
param_1[3] = param_1[3] ^ 0x39549dd6e1299b;
param_1[0] = param_1[0] + 0xff80a83276856f6b;
param_1[0] = param_1[0] + 0x3869018f758dd0;
param_1[0] = param_1[0] + 0xfff507f694ac1618;
param_1[0] = param_1[0] + 0xffaef9a6a60ac41c;
param_1[2] = param_1[2] ^ 0x4bb739ae97e2b2;
param_1[0] = param_1[0] ^ 0xb9c189c728744;
param_1[3] = param_1[3] ^ 0x63b60e480e2904;
param_1[1] = param_1[1] + 0x70ea19e458d1dd;
param_1[0] = param_1[0] ^ 0x1c380c9255dc4a;
param_1[0] = param_1[0] ^ 0x72195b264896c6;
param_1[0] = param_1[0] + 0xb58f5721006db;
param_1[1] = param_1[1] + 0xfff1a19d465554d0;
param_1[1] = param_1[1] + 0x45c8dee1a136cd;
param_1[1] = param_1[1] + 0xff95aa1bc2ad9c07;
param_1[3] = param_1[3] + 0xffed79b44c733cd6;
param_1[0] = param_1[0] + 0x27d894eb9caa9b;
param_1[3] = param_1[3] + 0xff9cb13f334ec53a;
param_1[3] = param_1[3] + 0x3c2a0d8d36145a;
param_1[1] = param_1[1] + 0x30a473f940b5dd;
param_1[2] = param_1[2] + 0x7239ea8aa2bc49;
param_1[1] = param_1[1] + 0x71e89e42b8b132;
param_1[1] = param_1[1] + 0xff887455a5eb36fd;
param_1[2] = param_1[2] + 0xffc07313a3962d72;
param_1[2] = param_1[2] + 0xffcf924d075d2a72;
param_1[1] = param_1[1] ^ 0x3707089012b521;
param_1[2] = param_1[2] + 0x12b99b0e57e3bb;
param_1[1] = param_1[1] + 0x3e897bb78bc162;
param_1[2] = param_1[2] + 0xffc244c1f804fc9b;
param_1[3] = param_1[3] ^ 0x21e211817f468b;
param_1[3] = param_1[3] + 0x44c0052fcca332;
param_1[1] = param_1[1] + 0x4f53af9faf8acf;
param_1[1] = param_1[1] + 0x2fda660863a649;
param_1[1] = param_1[1] + 0xffa9f06d0990b3ac;
param_1[2] = param_1[2] + 0x2e93addef2df4f;
param_1[3] = param_1[3] + 0x4531b2344b641b;
param_1[3] = param_1[3] + 0xfff8e89a72f8e26c;
param_1[1] = param_1[1] + 0x15c6da9bc36ed0;
param_1[2] = param_1[2] ^ 0x738278f8599e2d;
param_1[1] = param_1[1] ^ 0x44dd76d42e4513;
param_1[1] = param_1[1] + 0xffb57183e089ceb4;
param_1[2] = param_1[2] ^ 0x27972fbdfd287c;
param_1[0] = param_1[0] ^ 0x7eb9039a2b6bf0;
param_1[2] = param_1[2] + 0xffc75c67f5de1b31;

# FUN_00101346
param_1[0] = param_1[0] ^ 0x131e29f760409;
param_1[1] = param_1[1] + 0x23fe2dd7650a73;
param_1[1] = param_1[1] + 0xfff70308e97acf79;
param_1[2] = param_1[2] + 0xffb870f6f2950920;
param_1[0] = param_1[0] ^ 0x58bd244826ef43;
param_1[2] = param_1[2] + 0xffdc5874e8d03bbc;
param_1[1] = param_1[1] + 0xffb3ce0944bbfc19;
param_1[0] = param_1[0] ^ 0x38b3e1c4b3be14;
param_1[3] = param_1[3] ^ 0x6de4b0dccee1f8;
param_1[2] = param_1[2] + 0x48e99a2ccfbefa;
param_1[2] = param_1[2] + 0x2803831f197314;
param_1[2] = param_1[2] ^ 0x7fd3195c5e8bfb;
param_1[1] = param_1[1] + 0x2311f9e5515a6d;
param_1[3] = param_1[3] + 0x29e99994341bad;
param_1[2] = param_1[2] + 0xffa46f41e698229f;
param_1[0] = param_1[0] ^ 0x16097f9beb9df8;
param_1[2] = param_1[2] ^ 0x58f5f5f9e64f77;
param_1[2] = param_1[2] + 0xffce81bd3383de95;
param_1[0] = param_1[0] + 0x1437a45ffed077;
param_1[2] = param_1[2] + 0x4ec7609899b599;
param_1[3] = param_1[3] + 0x77832406a422ee;
param_1[0] = param_1[0] ^ 0xa299bfabd147f;
param_1[0] = param_1[0] + 0xff9731d63e0a4ce9;
param_1[0] = param_1[0] ^ 0x3ea0b669b87301;
param_1[0] = param_1[0] ^ 0x7bc3ff2762eeb0;
param_1[0] = param_1[0] + 0x2ff3559df23d95;
param_1[2] = param_1[2] + 0xffb0934ca254c450;
param_1[0] = param_1[0] + 0xff8b3b8d33d104e1;
param_1[3] = param_1[3] ^ 0x2f268e55029508;
param_1[2] = param_1[2] + 0xffe1c76d94c5b270;
param_1[3] = param_1[3] ^ 0x5575918734e1cd;
param_1[0] = param_1[0] + 0xffe368f50fe7ff81;
param_1[0] = param_1[0] ^ 0x22b615021c1680;
param_1[0] = param_1[0] + 0xff95c819c49f5170;
param_1[2] = param_1[2] + 0x485e655976a7ee;
param_1[0] = param_1[0] + 0x6f4847b022b253;
param_1[1] = param_1[1] ^ 0x392622311d6f3d;
param_1[1] = param_1[1] + 0xffb3096849dd7eb3;
param_1[3] = param_1[3] ^ 0x6e8b5de620fa;
param_1[3] = param_1[3] + 0x21d4322fefd286;
param_1[3] = param_1[3] + 0xffe14e96454625c5;
param_1[3] = param_1[3] ^ 0x4757d3b35495bb;
param_1[1] = param_1[1] + 0xffc4845886e53673;
param_1[0] = param_1[0] ^ 0x57617d2db4d1c4;
param_1[0] = param_1[0] ^ 0x69bd97ec881da;
param_1[2] = param_1[2] ^ 0x57ac6bbc11593;
param_1[2] = param_1[2] ^ 0x5c2cbf22512aa3;
param_1[2] = param_1[2] + 0x1860e298e3c0d5;
param_1[2] = param_1[2] + 0xffe6f1b24728fb11;
param_1[0] = param_1[0] + 0x4561b3931db109;
param_1[0] = param_1[0] ^ 0x1a70a95138d536;
param_1[2] = param_1[2] + 0x32ff8082367e19;
param_1[3] = param_1[3] + 0xff99a53e605869f2;
param_1[0] = param_1[0] + 0x1e359449108efb;
param_1[0] = param_1[0] + 0xff9338172cb899f9;
param_1[0] = param_1[0] + 0x33dbc3093cba9e;
param_1[1] = param_1[1] + 0x7d005d760e8a00;
param_1[0] = param_1[0] ^ 0x630abe094f2fcb;
param_1[2] = param_1[2] ^ 0x5c693ca6ad4098;
param_1[2] = param_1[2] ^ 0x1218c2c1fc6aab;
param_1[2] = param_1[2] ^ 0x78d35fbb138c9c;
param_1[3] = param_1[3] + 0x42dfb926a777d2;
param_1[3] = param_1[3] ^ 0x3f60fd507495c5;
param_1[1] = param_1[1] + 0x2cca6aa235fa04;
param_1[0] = param_1[0] + 0x5a8e68db17f162;
param_1[0] = param_1[0] + 0x1287bd45883bda;
param_1[0] = param_1[0] + 0xffe7b46bbeb822c6;
param_1[3] = param_1[3] + 0x5234b2a7901fd8;
param_1[3] = param_1[3] + 0xa856e4c03b946;
param_1[1] = param_1[1] ^ 0x6312ec05f527a4;
param_1[1] = param_1[1] + 0x46ce8a9c234e2f;
param_1[3] = param_1[3] + 0x171cfaebba97ed;

# FUN_00100c8c
param_1[2] = param_1[2] ^ 0x21552380a54ebd;
param_1[2] = param_1[2] ^ 0x217fe5a723014c;
param_1[2] = param_1[2] + 0xff929930c56e6594;
param_1[2] = param_1[2] ^ 0x7eb96f8929799a;
param_1[3] = param_1[3] + 0x67d0ff39897513;
param_1[3] = param_1[3] + 0x26a2f35c92df10;
param_1[2] = param_1[2] + 0xffd5d8a901dbebd6;
param_1[2] = param_1[2] + 0xad9fcf45aef6;
param_1[2] = param_1[2] + 0xffc53d1702ef8aa8;
param_1[0] = param_1[0] + 0x591ac5d1939c8b;
param_1[2] = param_1[2] ^ 0x33d94a84565532;
param_1[2] = param_1[2] ^ 0x308afb7e01e13e;
param_1[3] = param_1[3] + 0xffb48db7039082e1;
param_1[2] = param_1[2] ^ 0x55662e74858cf1;
param_1[3] = param_1[3] + 0xffa5b828a6179210;
param_1[1] = param_1[1] ^ 0x1638c6225c560d;
param_1[2] = param_1[2] ^ 0x40641fcdaf2a6d;
param_1[0] = param_1[0] + 0x1907586d8aaec6;
param_1[1] = param_1[1] ^ 0x2ac0e1d87fbfd3;
param_1[0] = param_1[0] + 0x4903ecf455fa05;
param_1[1] = param_1[1] + 0xff84efef75a89283;
param_1[2] = param_1[2] ^ 0x575e02c2ec2e98;
param_1[2] = param_1[2] ^ 0x5686c924044043;
param_1[0] = param_1[0] + 0xffa75728515de781;
param_1[0] = param_1[0] + 0x6c40d33a5de8b4;
param_1[0] = param_1[0] + 0xffae776809930118;
param_1[1] = param_1[1] + 0x77250c081305ce;
param_1[2] = param_1[2] + 0xffeff0d64a3fb770;
param_1[3] = param_1[3] + 0x1106386668917b;
param_1[2] = param_1[2] ^ 0x2a958285eaabc6;
param_1[1] = param_1[1] + 0x17e82fdc4bb7e6;
param_1[2] = param_1[2] + 0x6e5b6deacda2b3;
param_1[1] = param_1[1] + 0xffe4362cd469721d;
param_1[1] = param_1[1] ^ 0x46a8ddb8e7831e;
param_1[0] = param_1[0] + 0x5ef639bb0d96fc;
param_1[3] = param_1[3] ^ 0x540dd0d8537808;
param_1[3] = param_1[3] + 0xffd7468d44d84bfc;
param_1[2] = param_1[2] + 0xffb5048de8c6e26a;
param_1[0] = param_1[0] ^ 0x457b282105f5ff;
param_1[1] = param_1[1] ^ 0x2eff779ebf04ee;
param_1[1] = param_1[1] ^ 0x282c4c9602a8d1;
param_1[0] = param_1[0] ^ 0x5892a99ecd56db;
param_1[1] = param_1[1] + 0x7306fd8fb4ac48;
param_1[3] = param_1[3] + 0x4b3f6ca9126599;
param_1[3] = param_1[3] + 0xffed5514bbd0b395;
param_1[0] = param_1[0] + 0x19b2a80c1ebde0;
param_1[2] = param_1[2] ^ 0x34ab995333d7bc;
param_1[0] = param_1[0] ^ 0x4b803835540e77;
param_1[2] = param_1[2] ^ 0x4aaf3dd459117d;
param_1[3] = param_1[3] ^ 0x45b9bf142dd7b9;
param_1[0] = param_1[0] + 0xffdae06e2a1c7254;
param_1[1] = param_1[1] + 0xff805d1980ad21aa;
param_1[0] = param_1[0] + 0xff8aba0c42d40896;
param_1[0] = param_1[0] + 0x425422cc59e30;
param_1[0] = param_1[0] + 0x235f71339ac927;
param_1[2] = param_1[2] + 0xffb282c744cb6616;
param_1[2] = param_1[2] + 0xffa61489eb15d360;
param_1[0] = param_1[0] ^ 0x8db3daacc3ff9;
param_1[2] = param_1[2] ^ 0x97368bc6e7d41;
param_1[3] = param_1[3] ^ 0x86c96f6b4510f;
param_1[2] = param_1[2] ^ 0x1951f11deeb2fa;
param_1[1] = param_1[1] + 0x5dc2de99056b51;
param_1[2] = param_1[2] + 0xffb654da8cc4cb5f;

# FUN_00100786
param_1[3] = param_1[3] + 0xffdb0267f30481de;
param_1[0] = param_1[0] + 0xd349975ed71ce;
param_1[3] = param_1[3] + 0x396b3ec36373cc;
param_1[3] = param_1[3] ^ 0x2d2d96a9d4da30;
param_1[2] = param_1[2] ^ 0x656498272858da;
param_1[2] = param_1[2] + 0xffb3ad5ab10bc1f3;
param_1[0] = param_1[0] + 0x23b2f30be0e9ab;
param_1[0] = param_1[0] + 0xff99bef8c799559b;
param_1[0] = param_1[0] + 0xffe049bda2d90572;
param_1[2] = param_1[2] + 0xff9d4568f99d45eb;
param_1[2] = param_1[2] ^ 0x26ed48b4153eb0;
param_1[2] = param_1[2] ^ 0x1af75e7b5b8c5f;
param_1[2] = param_1[2] + 0xffe9fc2941b7bd92;
param_1[1] = param_1[1] ^ 0x4b4b690f995f73;
param_1[0] = param_1[0] + 0xffa3bcbff21dd191;
param_1[2] = param_1[2] ^ 0x6feb10d533c4b1;
param_1[1] = param_1[1] + 0xffb8a8e39fec3250;
param_1[2] = param_1[2] + 0xffdb2496d81b4293;
param_1[0] = param_1[0] + 0xffb778b645f31de9;
param_1[0] = param_1[0] ^ 0x531e0306cda7a9;
param_1[2] = param_1[2] ^ 0x3521f52cd98bf4;
param_1[1] = param_1[1] + 0xff880d1e8951a4a0;
param_1[2] = param_1[2] + 0x3858d7d314a793;
param_1[2] = param_1[2] + 0xffd7c92ed6f1e27a;
param_1[1] = param_1[1] + 0x37f1e8ac57fd21;
param_1[2] = param_1[2] + 0x794d667495ec53;
param_1[0] = param_1[0] + 0xf80ea376dfe9c;
param_1[2] = param_1[2] + 0x7077ef6357df45;
param_1[1] = param_1[1] + 0xfffe413b9b12d6da;
param_1[3] = param_1[3] + 0x562536f5f8bacf;
param_1[3] = param_1[3] + 0xff9f07032cf0845d;
param_1[0] = param_1[0] ^ 0x4ba91df7d06027;
param_1[0] = param_1[0] + 0xfff6ae6bcf2ebbbc;
param_1[3] = param_1[3] ^ 0x55cdaa7dfb2afc;
param_1[3] = param_1[3] + 0x318ce149b3a1fc;
param_1[3] = param_1[3] + 0xffd5d916adc11571;
param_1[0] = param_1[0] + 0xffc3560b3c7ef5e9;
param_1[1] = param_1[1] + 0xa8c0f5e148a9e;
param_1[2] = param_1[2] ^ 0x7b607330d80f26;
param_1[0] = param_1[0] ^ 0x3c139ff1892f4f;
param_1[1] = param_1[1] + 0x1f63d4725b825e;
param_1[3] = param_1[3] + 0x6be58b7a89dd9d;
param_1[1] = param_1[1] ^ 0x67b81b10716f5;
param_1[1] = param_1[1] + 0x70efa9f526c942;
param_1[3] = param_1[3] ^ 0x411eb7ecadc3cb;
param_1[3] = param_1[3] ^ 0x250c9395e3a054;
param_1[0] = param_1[0] + 0x78f186d15f1e3b;

# compare_function
s.add(param_1[0] ==  0x3167deae217139c1)
s.add(param_1[1] ==  0x6745aeaf0c9a62e5)
s.add(param_1[2] ==  0x62664d91c2da0c7b)
s.add(param_1[3] ==  0x7ee01bea8defde65)

print(s.check())
model = s.model()
flag_bytes = b""

for i in inp:
    flag_bytes += long_to_bytes(model[i].as_long())[::-1]

print(flag_bytes)

Flag: akasec{1n_my_b4g_0n3_s3c0nd_0n3}

Packeta (460 pts)

Description

Balança o ombrin', vai, vai Balança o ombrin', vai, vai

Balança o ombrin' Jogadinha do Packeta

Author: Pengolian

Solution

Given 2 ELF 64 bit files which are flag and packeta. First, open packeta using IDA. There are many function in the program, rename each function.

packeta - main
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 v3; // rdi
  __int64 v4; // rdx
  __int64 v5; // r8
  __int64 v6; // r9
  __int64 v7; // rdx
  __int64 v8; // r8
  __int64 v9; // r9
  __int64 v10; // rdx
  __int64 v11; // r8
  __int64 v12; // r9
  int fd; // [rsp+1Ch] [rbp-54h]
  __int64 v15; // [rsp+20h] [rbp-50h] BYREF
  void *v16; // [rsp+28h] [rbp-48h]
  size_t len; // [rsp+30h] [rbp-40h]
  _BYTE *v18; // [rsp+38h] [rbp-38h]
  void *v19; // [rsp+40h] [rbp-30h]
  void *v20; // [rsp+48h] [rbp-28h]
  unsigned __int64 v21; // [rsp+58h] [rbp-18h]

  v21 = __readfsqword(0x28u);
  v16 = 0LL;
  if ( a1 <= 1 )
  {
    printf("Usage:\n$> %s your_elf_binary", *a2);
    exit(1);
  }
  fd = open(a2[1], 0, a3);
  if ( !fd )
    exit(1);
  len = lseek(fd, 0LL, 2);
  if ( len == -1LL )
  {
    close(fd);
    exit(1);
  }
  v16 = mmap(0LL, len, 3, 2, fd, 0LL);
  if ( v16 == (void *)-1LL )
    exit(1);
  close(fd);
  v18 = malloc(0x40uLL);
  if ( !v18 )
    exit(1);
  if ( !sub_17CD(v16, v18) )
    exit(1);
  v19 = malloc(8LL * *((unsigned __int16 *)v18 + 30));
  if ( !v19 )
    exit(1);
  v3 = 8LL * *((unsigned __int16 *)v18 + 28);
  v20 = malloc(v3);
  if ( !v20 )
    exit(1);
  call_memcpy_1(v3, (__int64)v18, v4, (__int64)v19, v5, v6, v15, (__int64)v16, len, (__int64)v18, (__int64)v19);
  call_memcpy_2(
    v3,
    (__int64)v18,
    v7,
    (__int64)v19,
    v8,
    v9,
    v15,
    (__int64)v16,
    len,
    (__int64)v18,
    (int)v19,
    (__int64)v20);
  generate_key();
  call_rc4(v3, (__int64)v18, v10, (__int64)v19, v11, v12, v15, (__int64)v16, len, (__int64)v18, (__int64)v19);
  write_to_file((__int64)&v15);
  return 0LL;
}
  • generate_key function

unsigned __int64 sub_1CE2()
{
  int i; // [rsp+8h] [rbp-68h]
  time_t timer; // [rsp+10h] [rbp-60h] BYREF
  __int64 v3; // [rsp+18h] [rbp-58h]
  char v4[72]; // [rsp+20h] [rbp-50h] BYREF
  unsigned __int64 v5; // [rsp+68h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v3 = 4919LL;
  time(&timer);
  srand(v3 + timer % 500);
  strcpy(v4, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
  for ( i = 0; i <= 15; ++i )
    byte_5020[i] = v4[rand() % 62];
  return v5 - __readfsqword(0x28u);
}

So basically it generate key based on (current time % 500) + 4919. From that information we know that the possibility of the key only 500 (possible to brute).

  • call_rc4 function

unsigned __int64 __fastcall sub_1464(
        __int64 a1,
        __int64 a2,
        __int64 a3,
        __int64 a4,
        __int64 a5,
        __int64 a6,
        int a7,
        __int64 a8,
        int a9,
        __int64 a10,
        __int64 a11)
{
  unsigned __int64 result; // rax
  unsigned __int64 i; // [rsp+0h] [rbp-10h]
  void *ptr; // [rsp+8h] [rbp-8h]

  for ( i = 0LL; ; ++i )
  {
    result = *(unsigned __int16 *)(a10 + 60);
    if ( i >= result )
      break;
    ptr = sub_19C8(a8, *(_QWORD *)(a11 + 8LL * *(unsigned __int16 *)(a10 + 62)), **(_DWORD **)(8 * i + a11));
    if ( (unsigned int)sub_13F8(ptr) )
      rc4(a8 + *(_QWORD *)(*(_QWORD *)(8 * i + a11) + 24LL), *(_QWORD *)(*(_QWORD *)(8 * i + a11) + 32LL));
    free(ptr);
  }
  return result;
}

Lets take a look on rc4 function

unsigned __int64 __fastcall sub_1C66(__int64 a1, __int64 a2)
{
  char v3[264]; // [rsp+10h] [rbp-110h] BYREF
  unsigned __int64 v4; // [rsp+118h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  sub_1A84(byte_5020, v3);
  sub_1B5C(v3, a1, a2);
  return v4 - __readfsqword(0x28u);
}

From above code we can confirm that byte_5020 used as the key for rc4 function. To know the ciphertext values we can debug the executable using GDB.

pie b 0x1CC6
gef➤  x/32bx 0x00007ffff7fb8060
0x7ffff7fb8060:	0x4d	0x75	0xac	0xea	0x75	0xab	0x78	0x07
0x7ffff7fb8068:	0x90	0x58	0x8e	0x25	0x07	0x84	0x3f	0x73
0x7ffff7fb8070:	0x2b	0xa2	0x70	0x40	0x78	0x62	0x4b	0xfd
0x7ffff7fb8078:	0x65	0xf0	0x9b	0x07	0x58	0x44	0x9d	0xca

The ciphertext values start with 0x4d75. Check on flag binary to findout on which section those ciphertext.

From image above we can confirm that the ciphertext section is on .text section. To get the valid key we can do bruteforce and validate manually which plaintext consist of valid assembly instruciton because the first ciphertext is the start function. Below is my script

from Crypto.Cipher import ARC4
from ctypes import CDLL
from capstone import *
import string

md = Cs(CS_ARCH_X86, CS_MODE_64)

libc = CDLL("libc.so.6")
ct = [0x4d, 0x75, 0xac, 0xea, 0x75, 0xab, 0x78, 0x7, 0x90, 0x58, 0x8e, 0x25, 0x7, 0x84, 0x3f, 0x73, 0x2b, 0xa2, 0x70, 0x40, 0x78, 0x62, 0x4b, 0xfd, 0x65, 0xf0, 0x9b, 0x7, 0x58, 0x44, 0x9d, 0xca]
v4 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

for i in range(500):
	libc.srand(4919 + i)
	key = ""
	for j in range(16):
		key += v4[libc.rand() % 62]
	cipher = ARC4.new(key.encode())
	asm = cipher.decrypt(bytes(ct))
	for j in md.disasm(asm, 0x401000):
		print(i, j)
	print()

For the comparison we can use the standard start function, such as from packeta file.

So i == 127 looks like the correct value because it result valid assembly like standard start function. To get the rest plaintext we can debug the program and set the value for the (current_time % 500).

pie b 0x1d49

Continue the process then run the new generated ELF named new.

Flag: AKASEC{h4lf_p4ck_h4lf_7h3_fl46}

Mips (477 pts)

Description

check out my 16 star pb (note: you need ares to run the rom properly)

Author: miyako

nc 20.80.240.190 4321

Solution

Given Nintendo 64 ROM image. During the competition i found good reference about nintedo 64 reverse engineering. From the description we know that we can run the rom using ares. In this case i install the emulator on ubuntu. To load the rom we can click Load -> Nintendo -> Nintendo 64.

Setup the input mapping by click Settings -> Input.

Press some random button and it will reflected on screen, to submit the button we can press enter button (start).

Next, we need to decompile the rom. I use ghidra with N64LoaderWV plugin to do that.

Searching for "wrong" string then we will found the validation program.

void FUN_8000b4e0(void)

{
  undefined uVar2;
  longlong lVar1;
  uint uVar3;
  int iVar4;
  int unaff_gp_lo;
  undefined4 local_48;
  int iStack_44;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  
  FUN_80007340(&local_48);
  if ((*(unaff_gp_lo + -0x7e6c) == '\0') && (uVar3 = (&DAT_ffff8195)[unaff_gp_lo], iStack_44 != 0))
  {
    if ((&DAT_ffff8195)[unaff_gp_lo] == 0) {
      iVar4 = -0x7ffd0000;
      _DAT_800280b0 = 0;
      _PTR_DAT_800280b8 = 0;
      _PTR_DAT_800280c0 = 0;
      PTR_DAT_800280c8 = 0x0;
      PTR_DAT_800280cc._0_2_ = 0;
      uVar2 = FUN_8000b200(CONCAT44(local_48,iStack_44),local_40,local_38,local_30);
      *(iVar4 + -0x7f50) = uVar2;
      (&DAT_ffff8195)[unaff_gp_lo] = 1;
      return;
    }
    uVar2 = FUN_8000b200(CONCAT44(local_48,iStack_44),local_40,local_38,local_30);
    (&DAT_800280b0)[uVar3] = uVar2;
    (&DAT_ffff8195)[unaff_gp_lo] = uVar3 + 1;
    if ((uVar3 + 1 & 0xff) == 0x1e) {
      lVar1 = FUN_80010ed8(0xffffffff800280b0,0xffffffff800270c8,0x1e);
      if (lVar1 == 0) {
        *(unaff_gp_lo + -0x7f5c) = s_correct!_80019be0;
        *(unaff_gp_lo + -0x7e6c) = 1;
      }
      else {
        *(unaff_gp_lo + -0x7f5c) = s_wrong_80019bf0;
        (&DAT_ffff8195)[unaff_gp_lo] = 0;
      }
    }
  }
  return;
}

From above code we got some information

  • Line 30: Our input mapped to some constant value

  • Line 33: Input length is 0x1e, we can also confirm through user interface by input more than 30 button then it will reset

  • Line 34: Our mapped input validated with constant value at (DAT_800270c8)

Now we need to get the valid input mapping, one of the way to do that is by debugging. Click Settings -> Debug then enable debugging with below options.

After that, use gdb-multiarch to connect to gdb server.

target remote localhost:9123
ctrl+c
set endian big
x/20i 0x8000b4e0

Then breakpoint at 0x8000b53c.

break *0x8000b53c
c

Press up button (for example), then the breakpoint will be hitten. Look at v0 register to know the mapped value for up button.

Do the same thing until got all mapped input then create script to get the reflected input on screen.

dict = {}
dict[2] = 'U'
dict[5] = 'L'
dict[9] = 'R'
dict[1] = 'D'
dict[0xa] = 'CU'
dict[0x14] = 'CL'
dict[0xf] = 'CD'
dict[0x19] = 'CR'
dict[0x7] = 'B'
dict[0x4] = 'A'
dict[0xb] = 'LR'
dict[0xc] = 'RR'
dict[0x3] = 'Z'

target_button = [0x03,0x0C,0x0A,0x0A,0x0A,0x0A,0x14,0x01,0x01,0x0A,0x04,0x07,0x19,0x09,0x01,0x0A,0x02,0x05,0x09,0x07,0x02,0x0C,0x09,0x07,0x0A,0x0C,0x0A,0x03,0x09,0x03]

button = ""

for i in target_button:
	button += dict[i]

print(button)

Flag: akasec{m1ps_1s_c00l_l0l}

Orgalorg (498 pts)

Description

Did you know that Gunter is literally Orgalorg, a primordial cosmic entity, feared as the Breaker of Worlds, disguised as a penguin on earth...

nc 20.80.240.190 1235

Author: pengolian

Solution

Given ELF 64 bit file, open it using IDA.

__int64 __fastcall main(int a1, const char **a2, char **a3, int a4, int a5, int a6)
{
  const char *v6; // rbp
  size_t v7; // rax
  size_t v8; // rbx
  __int64 *v10; // rdi
  size_t v11; // [rsp+8h] [rbp-60h] BYREF
  __int64 v12[2]; // [rsp+10h] [rbp-58h] BYREF
  __int64 v13[9]; // [rsp+20h] [rbp-48h] BYREF

  v13[3] = __readfsqword(0x28u);
  func_1(a1, a2, a3, a4, a5, a6); 
  if ( dword_17240 )
  {
    func_2();
    return 0LL;
  }
  v6 = *a2;
  v12[0] = v13;
  if ( !v6 )
    std::__throw_logic_error("basic_string: construction from null is not valid");
  v7 = strlen(v6);
  v11 = v7;
  v8 = v7;
  if ( v7 > 0xF )
  {
    v12[0] = std::string::_M_create(v12, &v11, 0LL);
    v10 = v12[0];
    v13[0] = v11;
    goto LABEL_12;
  }
  if ( v7 != 1 )
  {
    if ( !v7 )
      goto LABEL_6;
    v10 = v13;
LABEL_12:
    memcpy(v10, v6, v8);
    goto LABEL_6;
  }
  LOBYTE(v13[0]) = *v6;
LABEL_6:
  v12[1] = v11;
  *(v12[0] + v11) = 0;
  sub_5950(v12);
  std::string::_M_dispose(v12);
  return 0LL;
}

So in main function there are two user defined function which are func_1 and sub_5950. Lets take a look on func_1. At the time of competition i've renamed some function while debugging.

unsigned __int64 __fastcall sub_5150()
{
  __m128i *v0; // rax
  __m128i v1; // xmm2
  __m128i v2; // xmm3
  char *LOGNAME; // rbx
  __int32 *v4; // rax
  __int32 v5; // r9d
  char *OGP; // r14
  size_t v7; // rax
  size_t v8; // rax
  __m128i *v10; // rax
  __m128i v11; // xmm7
  void *v12[2]; // [rsp+0h] [rbp-98h] BYREF
  __int32 *v13; // [rsp+10h] [rbp-88h]
  __m128i si128; // [rsp+20h] [rbp-78h] BYREF
  __int64 v15; // [rsp+30h] [rbp-68h]
  __int64 v16; // [rsp+38h] [rbp-60h]
  char *name[2]; // [rsp+40h] [rbp-58h] BYREF
  __int64 v18[3]; // [rsp+50h] [rbp-48h] BYREF
  unsigned __int64 v19; // [rsp+68h] [rbp-30h]

  v19 = __readfsqword(0x28u);
  if ( anti_debug_1() )
    goto LABEL_22;
  LODWORD(v16) = -1073741632;
  v15 = 0xC00000C1400000C0LL;
  v13 = 0LL;
  si128 = _mm_load_si128(&xmmword_F130);
  *v12 = 0LL;
  v0 = operator new(0x1CuLL);
  v12[0] = v0;
  v1 = _mm_load_si128(&si128);
  v2 = _mm_loadu_si128(&si128.m128i_i8[12]);
  v13 = &v0[1].m128i_i32[3];
  *v0 = v1;
  *(v0 + 12) = v2;
  v12[1] = &v0[1].m128i_u64[1] + 4;
  get_string(name, v12);
  LOGNAME = getenv(name[0]);                    // getenv("LOGNAME")
  if ( name[0] != v18 )
    operator delete(name[0], v18[0] + 1);
  if ( v12[0] )
    operator delete(v12[0], v13 - v12[0]);
  si128.m128i_i32[2] = 1610612930;
  v13 = 0LL;
  si128.m128i_i64[0] = 0x800000C0800000C1LL;
  *v12 = 0LL;
  v4 = operator new(0xCuLL);
  v12[0] = v4;
  v5 = si128.m128i_i32[2];
  v13 = v4 + 3;
  *v4 = si128.m128i_i64[0];
  v4[2] = v5;
  v12[1] = v4 + 3;
  get_string(name, v12);
  OGP = getenv(name[0]);                        // getenv("OGP")
  if ( name[0] != v18 )
    operator delete(name[0], v18[0] + 1);
  if ( v12[0] )
    operator delete(v12[0], v13 - v12[0]);
  if ( LOGNAME )
  {
    v7 = strlen(LOGNAME);
    std::string::_M_replace(&LOGNAME_1, 0LL, LOGNAME_LENGTH, LOGNAME, v7);
  }
  if ( OGP )
  {
    v8 = strlen(OGP);
    std::string::_M_replace(&OGP_1, 0LL, OGP_LENGTH, OGP, v8);
  }
  if ( OGP_LENGTH )
  {
    if ( sub_BBC0(&OGP_1) )                     // check length OGP and digits
    {
      dword_171E0 = sub_4730();
      LODWORD(v15) = 0x600000C6;
      v13 = 0LL;
      si128 = _mm_load_si128(&xmmword_F140);
      *v12 = 0LL;
      v10 = operator new(0x14uLL);
      v11 = _mm_load_si128(&si128);
      v12[0] = v10;
      v10[1].m128i_i32[0] = v15;
      *v10 = v11;
      v13 = &v10[1].m128i_i32[1];
      v12[1] = v10[1].m128i_i64 + 4;
      get_string(name, v12);
      prctl(15, name[0], 0LL, 0LL, 0LL);        // prctl(PR_SET_NAME,"sleep")
      if ( name[0] != v18 )
        operator delete(name[0], v18[0] + 1);
      if ( v12[0] )
        operator delete(v12[0], v13 - v12[0]);
      dword_17240 = 1;
      return v19 - __readfsqword(0x28u);
    }
LABEL_22:
    exit(1);
  }
  return v19 - __readfsqword(0x28u);
}
  • anti_debug_1

    • anti debug function, will exit the process if debugging detected

    • will open /proc/self/status to check debugging status

    • We can easily bypass the the anti debug by changing the return value

  • get_string

    • kind of string obfuscation, the function will return "plaintext" of obfuscated/encrypted string

  • sub_bbc0

    • check length of OGP and ensure that it constructed only from digits

  • prctl

    • set the process name to sleep

  • dword_17240

    • There will be set of dword_17240 variable to 1 if there is valid OGP and debugging not detected

Back to main function, after calling of func_1 there will be validation of dword_17240. If dword_17240 not zero it will call func_2. So lets take a look on func_2.

__int64 sub_45F0()
{
  __pid_t v0; // eax
  __pid_t v1; // eax
  int v2; // eax
  int v3; // ebx
  int v4; // eax
  int v5; // edi
  int v6; // edi
  int v7; // edi
  int v8; // edi
  int v9; // edi
  int v11; // edi
  int v13; // edi

  v0 = fork();
  if ( v0 < 0 )
    goto LABEL_24;
  if ( v0 )
    goto LABEL_23;
  if ( setsid() < 0 || (v1 = fork(), v1 < 0) )
LABEL_24:
    exit(1);
  if ( v1 )
LABEL_23:
    exit(0);
  umask(0);
  v2 = sysconf(4);
  v3 = v2;
  if ( v2 >= 0 )
  {
    v4 = (v2 + 1) & 7;
    if ( !v4 )
      goto LABEL_27;
    if ( v4 != 1 )
    {
      if ( v4 != 2 )
      {
        if ( v4 != 3 )
        {
          if ( v4 != 4 )
          {
            if ( v4 != 5 )
            {
              if ( v4 != 6 )
              {
                v13 = v3--;
                close(v13);
              }
              v5 = v3--;
              close(v5);
            }
            v6 = v3--;
            close(v6);
          }
          v7 = v3--;
          close(v7);
        }
        v8 = v3--;
        close(v8);
      }
      v9 = v3--;
      close(v9);
    }
    close(v3);
    if ( v3-- != 0 )
    {
LABEL_27:
      do
      {
        close(v3);
        close(v3 - 1);
        close(v3 - 2);
        close(v3 - 3);
        close(v3 - 4);
        close(v3 - 5);
        close(v3 - 6);
        v11 = v3 - 7;
        v3 -= 8;
        close(v11);
      }
      while ( v3 != -1 );
    }
  }
  return func_3();
}
  • fork

    • There is call of fork, so after calling fork the rest flow will be processed by the child process

    • Set follow fork mode to child on GDB to debug the child process

Next, take a look on func_3

// positive sp value has been detected, the output may be wrong!
__int64 sub_BDB0()
{
  int v0; // esi
  int v1; // edx
  int v2; // ecx
  int v3; // r8d
  int v4; // r9d
  char *v5; // rax
  _BYTE *v6; // r15
  size_t v7; // rax
  size_t v8; // rbp
  void *v9; // rsi
  _QWORD *v10; // rdi
  nfds_t v11; // r12
  struct pollfd *v12; // rax
  int v13; // ebp
  __int64 v14; // rax
  __int64 v15; // r13
  int v16; // r14d
  _QWORD *v17; // rdi
  __int64 v18; // rax
  int i; // r14d
  _QWORD *v20; // r12
  int v21; // eax
  int v23; // [rsp-118h] [rbp-80148h]
  void *v24; // [rsp-110h] [rbp-80140h] BYREF
  char *v25; // [rsp-108h] [rbp-80138h] BYREF
  char *v26; // [rsp-100h] [rbp-80130h]
  char *v27; // [rsp-F8h] [rbp-80128h]
  void *v28; // [rsp-F0h] [rbp-80120h]
  void *v29[2]; // [rsp-E8h] [rbp-80118h] BYREF
  __int64 v30; // [rsp-D8h] [rbp-80108h] BYREF
  void *v31[2]; // [rsp-C8h] [rbp-800F8h] BYREF
  _QWORD v32[2]; // [rsp-B8h] [rbp-800E8h] BYREF
  _BYTE v33[168]; // [rsp-A8h] [rbp-800D8h] BYREF
  char v34; // [rsp+0h] [rbp-80030h] BYREF
  __int64 v35; // [rsp+1000h] [rbp-7F030h] BYREF
  unsigned __int64 v36; // [rsp+7FFF0h] [rbp-40h]

  while ( &v34 != (&v35 - 0x10000) )
    ;
  v0 = dword_171E0;
  v36 = __readfsqword(0x28u);
  (sub_6750)(v33, dword_171E0);
  if ( anti_debug_1(v33, v0, v1, v2, v3, v4, v23, v24, v25, v26, v27, v28, v29[0], v29[1]) )
    exit(1);
  if ( (call_socket)(v33) )
  {
    if ( !(call_setsockopt)(v33) || !(call_fcntl)(v33) || !call_bind(v33) || !(call_listen)(v33) )
      (call_exit_1)(v33, 1LL);
    (call_memset)(v33);
    v5 = operator new(0x10uLL);
    v25 = v5;
    v27 = v5 + 16;
    *v5 = _mm_load_si128(&xmmword_14700);
    v26 = v5 + 16;
    get_string(v29, &v25);
    v6 = v29[0];
    v31[0] = v32;
    if ( !v29[0] )
      std::__throw_logic_error("basic_string: construction from null is not valid");
    v7 = strlen(v29[0]);                        // p455
    v24 = v7;
    v8 = v7;
    v9 = v7;
    if ( v7 > 0xF )
    {
      v31[0] = std::string::_M_create(v31, &v24, 0LL);
      v17 = v31[0];
      v32[0] = v24;
    }
    else
    {
      if ( v7 == 1 )
      {
        LOBYTE(v32[0]) = *v6;
LABEL_12:
        v10 = v32;
        goto LABEL_13;
      }
      if ( !v7 )
        goto LABEL_12;
      v17 = v32;
    }
    memcpy(v17, v6, v8);
    v9 = v24;
    v10 = v31[0];
LABEL_13:
    v31[1] = v9;
    *(v9 + v10) = 0;
    (call_string_assign)(v33, v31);
    if ( v31[0] != v32 )
      operator delete(v31[0], v32[0] + 1LL);
    if ( v29[0] != &v30 )
      operator delete(v29[0], v30 + 1);
    if ( v25 )
      operator delete(v25, v27 - v25);
    signal(17, handler);
LABEL_20:
    v11 = (get_arr_1)(v33);
    v12 = (call_a1_plus_4)(v33);
    if ( !poll(v12, v11, 172800000) )
      (call_exit_1)(v33, 1LL);
    v13 = 0;
    while ( 1 )
    {
      while ( 1 )
      {
        if ( v13 >= (get_arr_1)(v33) )
          goto LABEL_20;
        v15 = 8LL * v13;
        if ( *((call_a1_plus_4)(v33) + v15 + 6) )
          break;
LABEL_23:
        ++v13;
      }
      v16 = *((call_a1_plus_4)(v33) + 8LL * v13);
      if ( v16 == (get_arr_3)(v33) )
      {
        if ( !send_banner(v33) )    
          (call_exit_1)(v33, 1LL);
        goto LABEL_23;
      }
      v14 = (call_a1_plus_4)(v33);
      if ( (process_recv)(v33, *(v14 + 8LL * v13)) )
        goto LABEL_23;
      v18 = (call_a1_plus_4)(v33);
      (call_close_2)(v33, *(v18 + 8LL * v13));
      for ( i = v13; i < (get_arr_1)(v33); ++i )
      {
        v20 = ((call_a1_plus_4)(v33) + v15 + 8);
        *((call_a1_plus_4)(v33) + v15) = *v20;
        v15 += 8LL;
      }
      v21 = (get_arr_1)(v33);
      (get_arr_2)(v33, (v21 - 1));
    }
  }
  (call_close_1)(v33);
  return 1LL;
}
  • Line 50: initialize socket listening, bind to port 50009

  • Line 121: sending banner (during the initial connection)

  • Line 126: process our input

Next lets take a look on process_recv.

__int64 __fastcall process_recv(__int64 a1, int a2)
{
  _DWORD *v3; // r14
  size_t v4; // rax
  __int64 v5; // rdx
  __int64 v6; // r15
  ssize_t v7; // rax
  int input_length; // eax
  char *v9; // r15
  __int64 *v11; // r8
  char *v12; // r12
  __int64 v13; // r10
  __int64 v14; // r12
  unsigned int v15; // r8d
  unsigned int v16; // r9d
  __int64 v17; // r15
  __int64 v18; // rcx
  __int64 v19; // r9
  __int64 v20; // r11
  __int64 v21; // r15
  __int64 v22; // rcx
  __int64 v23; // r11
  __int64 v24; // r15
  __int64 v25; // rcx
  __int64 v26; // rdi
  __int64 v27; // rdx
  __int64 v28; // rsi
  __int64 v29; // r9
  __int64 v30; // r11
  __int64 v31; // r10
  __int64 v32; // r15
  __int64 v33; // rdi
  __int64 v34; // rcx
  __int64 v35; // rdx
  __int64 v36; // rsi
  size_t actual_input_length; // rdx
  unsigned __int64 last_of; // rax
  size_t v39; // r12
  __int64 *v40; // r11
  __int64 *v41; // rdx
  __int64 *v42; // rax
  __m128i v43; // xmm1
  __int64 v44; // rax
  __int64 *v45; // rdi
  __m128i v46; // xmm0
  __int64 v47; // r11
  __int64 v48; // rcx
  __int8 v49; // dl
  __int64 v50; // r10
  unsigned __int64 v51; // r11
  signed __int64 v52; // rax
  __int8 *v53; // rdi
  unsigned int v54; // edx
  unsigned int v55; // r9d
  unsigned int v56; // esi
  __int64 v57; // r10
  __int64 v58; // rcx
  __int64 v59; // rax
  __int64 v60; // r10
  __int64 v61; // r12
  __int64 v62; // rsi
  __int64 v63; // r10
  __int64 v64; // rcx
  __int64 v65; // rsi
  __int64 v67; // [rsp+18h] [rbp-2B0h] BYREF
  void *input_user_2; // [rsp+20h] [rbp-2A8h] BYREF
  __m128i n; // [rsp+28h] [rbp-2A0h] BYREF
  void *v70; // [rsp+40h] [rbp-288h]
  __int64 v71; // [rsp+48h] [rbp-280h]
  char s[8]; // [rsp+50h] [rbp-278h] BYREF
  __int64 v73; // [rsp+58h] [rbp-270h]
  void *v74; // [rsp+60h] [rbp-268h] BYREF
  __m128i v75; // [rsp+68h] [rbp-260h] BYREF
  __int64 v76; // [rsp+78h] [rbp-250h]
  char user_input[520]; // [rsp+80h] [rbp-248h] BYREF
  unsigned __int64 v78; // [rsp+288h] [rbp-40h]

  v78 = __readfsqword(0x28u);
  n.m128i_i32[0] = 1610612940;
  input_user_2 = 0xA00000CFA00000CFLL;
  v70 = s;
  v3 = operator new(0xCuLL);
  *v3 = 0xA00000CFA00000CFLL;
  v3[2] = 1610612940;
  v71 = 3LL;
  strcpy(s, ">> ");
  v74 = &v75.m128i_u64[1];
  v4 = strlen(s);
  if ( v4 != 1 )
  {
    if ( !v4 )
      goto LABEL_3;
    v11 = &v75.m128i_i64[1];
    v12 = s;
    if ( v4 >= 8 )
    {
      v14 = 8LL;
      v15 = v4 & 0xFFFFFFF8;
      v75.m128i_i64[1] = *s;
      v16 = (((v4 & 0xFFFFFFF8) - 1) >> 3) & 7;
      if ( (v4 & 0xFFFFFFF8) > 8 )
      {
        if ( !v16 )
          goto LABEL_104;
        if ( v16 != 1 )
        {
          if ( v16 != 2 )
          {
            if ( v16 != 3 )
            {
              if ( v16 != 4 )
              {
                if ( v16 != 5 )
                {
                  if ( v16 != 6 )
                  {
                    v76 = v73;
                    LODWORD(v14) = 16;
                  }
                  v17 = v14;
                  LODWORD(v14) = v14 + 8;
                  *(&v75.m128i_i64[1] + v17) = *&s[v17];
                }
                v18 = v14;
                LODWORD(v14) = v14 + 8;
                *(&v75.m128i_i64[1] + v18) = *&s[v18];
              }
              v19 = v14;
              LODWORD(v14) = v14 + 8;
              *(&v75.m128i_i64[1] + v19) = *&s[v19];
            }
            v20 = v14;
            LODWORD(v14) = v14 + 8;
            *(&v75.m128i_i64[1] + v20) = *&s[v20];
          }
          v21 = v14;
          LODWORD(v14) = v14 + 8;
          *(&v75.m128i_i64[1] + v21) = *&s[v21];
        }
        v22 = v14;
        v14 = (v14 + 8);
        *(&v75.m128i_i64[1] + v22) = *&s[v22];
        if ( v14 < v15 )
        {
LABEL_104:
          do
          {
            v23 = (v14 + 8);
            v24 = (v14 + 16);
            v25 = (v14 + 24);
            v26 = *&s[v23];
            v27 = *&s[v24];
            v28 = *&s[v25];
            *(&v75.m128i_i64[1] + v14) = *&s[v14];
            v29 = (v14 + 32);
            *(&v75.m128i_i64[1] + v23) = v26;
            v30 = (v14 + 40);
            v31 = *&s[v29];
            *(&v75.m128i_i64[1] + v24) = v27;
            v32 = (v14 + 48);
            v33 = *&s[v30];
            *(&v75.m128i_i64[1] + v25) = v28;
            v34 = (v14 + 56);
            v35 = *&s[v32];
            v14 = (v14 + 64);
            v36 = *&s[v34];
            *(&v75.m128i_i64[1] + v29) = v31;
            *(&v75.m128i_i64[1] + v30) = v33;
            *(&v75.m128i_i64[1] + v32) = v35;
            *(&v75.m128i_i64[1] + v34) = v36;
          }
          while ( v14 < v15 );
        }
      }
      v11 = (&v75.m128i_i64[1] + v14);
      v12 = &s[v14];
    }
    v13 = 0LL;
    if ( (v4 & 4) != 0 )
    {
      v13 = 4LL;
      *v11 = *v12;
      if ( (v4 & 2) == 0 )
      {
LABEL_24:
        if ( (v4 & 1) == 0 )
          goto LABEL_3;
LABEL_25:
        *(v11 + v13) = v12[v13];
        goto LABEL_3;
      }
    }
    else if ( (v4 & 2) == 0 )
    {
      goto LABEL_24;
    }
    *(v11 + v13) = *&v12[v13];
    v13 += 2LL;
    if ( (v4 & 1) == 0 )
      goto LABEL_3;
    goto LABEL_25;
  }
  v75.m128i_i8[8] = 62;
LABEL_3:
  v75.m128i_i64[0] = v4;
  v75.m128i_i8[v4 + 8] = 0;
  v5 = v75.m128i_i64[0];
  if ( v75.m128i_i64[0] )
  {
    v6 = 0LL;
    do
    {
      v7 = send(a2, v74 + v6, v5 - v6, 0);
      if ( v7 == -1 )
        break;
      v5 = v75.m128i_i64[0];
      v6 += v7;
    }
    while ( v75.m128i_i64[0] != v6 );
  }
  if ( v74 != &v75.m128i_u64[1] )
    operator delete(v74, v75.m128i_i64[1] + 1);
  if ( v70 != s )
    operator delete(v70, *s + 1LL);
  operator delete(v3, 0xCuLL);
  memset(user_input, 0, 0x200uLL);
  input_user_2 = &n.m128i_u64[1];
  n.m128i_i64[0] = 0LL;
  n.m128i_i8[8] = 0;
  v70 = s;
  v71 = 0LL;
  s[0] = 0;
  while ( 1 )
  {
    input_length = recv(a2, user_input, 0x1FEuLL, 0);
    if ( input_length != -1 )
      break;
    if ( *__errno_location() != 11 )
    {
      LODWORD(v9) = 0;
      goto LABEL_15;
    }
  }
  LODWORD(v9) = 0;
  if ( input_length )
  {
    user_input[input_length] = 0;
    actual_input_length = strlen(user_input);
    if ( 0x3FFFFFFFFFFFFFFFLL - n.m128i_i64[0] < actual_input_length )
      std::__throw_length_error("basic_string::append");
    std::string::_M_append(&input_user_2, user_input, actual_input_length);
    if ( std::string::find_first_of(&input_user_2, "\r\n", 0LL, 2LL) == -1 )
    {
      LODWORD(v9) = 1;
      goto LABEL_15;
    }
    last_of = std::string::find_last_of(&input_user_2, "\r\n", -1LL, 2LL);
    v74 = &v75.m128i_u64[1];
    v39 = last_of;
    v9 = input_user_2;
    if ( last_of > n.m128i_i64[0] )
      v39 = n.m128i_i64[0];
    v67 = v39;
    if ( v39 > 0xF )
    {
      v74 = std::string::_M_create(&v74, &v67, 0LL);
      v45 = v74;
      v75.m128i_i64[1] = v67;
    }
    else
    {
      if ( v39 == 1 )
      {
        v75.m128i_i8[8] = *input_user_2;
        goto LABEL_55;
      }
      if ( !v39 )
      {
LABEL_55:
        v40 = &v75.m128i_i64[1];
        goto LABEL_56;
      }
      v45 = &v75.m128i_i64[1];
    }
    memcpy(v45, v9, v39);
    v39 = v67;
    v40 = v74;
LABEL_56:
    v75.m128i_i64[0] = v39;
    *(v40 + v39) = 0;
    v41 = input_user_2;
    v42 = input_user_2;
    if ( input_user_2 == &n.m128i_u64[1] )
    {
      if ( v74 != &v75.m128i_u64[1] )
      {
        v46 = _mm_loadu_si128(&v75);
        input_user_2 = v74;
        n = v46;
        goto LABEL_69;
      }
    }
    else if ( v74 != &v75.m128i_u64[1] )
    {
      v43 = _mm_loadu_si128(&v75);
      v44 = n.m128i_i64[1];
      input_user_2 = v74;
      n = v43;
      if ( v41 )
      {
        v74 = v41;
        v75.m128i_i64[1] = v44;
LABEL_60:
        v75.m128i_i64[0] = 0LL;
        *v41 = 0;
        if ( v74 != &v75.m128i_u64[1] )
          operator delete(v74, v75.m128i_i64[1] + 1);
        LOBYTE(v9) = sus_func_1(a1, a2, &input_user_2) != 0;
        goto LABEL_15;
      }
LABEL_69:
      v74 = &v75.m128i_u64[1];
      v41 = &v75.m128i_i64[1];
      goto LABEL_60;
    }
    v47 = v75.m128i_i64[0];
    v48 = v75.m128i_i64[0];
    if ( !v75.m128i_i64[0] )
    {
LABEL_78:
      n.m128i_i64[0] = v47;
      *(v41 + v47) = 0;
      v41 = v74;
      goto LABEL_60;
    }
    if ( v75.m128i_i64[0] == 1 )
    {
      *input_user_2 = v75.m128i_i8[8];
      v47 = v75.m128i_i64[0];
      v41 = input_user_2;
      goto LABEL_78;
    }
    v49 = v75.m128i_i8[0];
    if ( v75.m128i_i32[0] >= 8u )
    {
      v50 = v75.m128i_u32[0];
      v51 = (input_user_2 + 8) & 0xFFFFFFFFFFFFFFF8LL;
      *input_user_2 = v75.m128i_i64[1];
      *(v42 + v50 - 8) = *(v75.m128i_i64 + v50);
      v52 = v42 - v51;
      v53 = &v75.m128i_i8[-v52 + 8];
      if ( ((v48 + v52) & 0xFFFFFFF8) >= 8 )
      {
        v54 = (v48 + v52) & 0xFFFFFFF8;
        v55 = 8;
        v9 = *v53;
        *v51 = *v53;
        v56 = ((v54 - 1) >> 3) & 7;
        if ( v54 > 8 )
        {
          if ( !v56 )
            goto LABEL_105;
          if ( v56 != 1 )
          {
            if ( v56 != 2 )
            {
              if ( v56 != 3 )
              {
                if ( v56 != 4 )
                {
                  if ( v56 != 5 )
                  {
                    if ( v56 != 6 )
                    {
                      *(v51 + 8) = *(v53 + 1);
                      v55 = 16;
                    }
                    v57 = v55;
                    v55 += 8;
                    *(v51 + v57) = *&v53[v57];
                  }
                  v58 = v55;
                  v55 += 8;
                  *(v51 + v58) = *&v53[v58];
                }
                v59 = v55;
                v55 += 8;
                v9 = *&v53[v59];
                *(v51 + v59) = v9;
              }
              v60 = v55;
              v55 += 8;
              *(v51 + v60) = *&v53[v60];
            }
            v61 = v55;
            v55 += 8;
            *(v51 + v61) = *&v53[v61];
          }
          v62 = v55;
          v55 += 8;
          *(v51 + v62) = *&v53[v62];
          if ( v55 < v54 )
          {
LABEL_105:
            do
            {
              *(v51 + v55) = *&v53[v55];
              v63 = v55 + 32;
              *(v51 + v55 + 8) = *&v53[v55 + 8];
              *(v51 + v55 + 16) = *&v53[v55 + 16];
              v64 = v55 + 40;
              v65 = v55 + 48;
              *(v51 + v55 + 24) = *&v53[v55 + 24];
              v9 = (v55 + 56);
              v55 += 64;
              *(v51 + v63) = *&v53[v63];
              *(v51 + v64) = *&v53[v64];
              *(v51 + v65) = *&v53[v65];
              *&v9[v51] = *&v9[v53];
            }
            while ( v55 < v54 );
          }
        }
      }
    }
    else
    {
      if ( (v75.m128i_i8[0] & 4) != 0 )
      {
        *input_user_2 = v75.m128i_i32[2];
        *(v42 + v47 - 4) = *(&v75.m128i_i32[1] + v47);
        v48 = v75.m128i_i64[0];
        v42 = input_user_2;
        goto LABEL_77;
      }
      if ( !v75.m128i_i32[0] )
      {
LABEL_77:
        v47 = v48;
        v41 = v42;
        goto LABEL_78;
      }
      LODWORD(v9) = v75.m128i_u8[8];
      *input_user_2 = v75.m128i_i8[8];
      if ( (v49 & 2) != 0 )
      {
        *(v42 + v47 - 2) = *(&v75.m128i_i16[3] + v47);
        v48 = v75.m128i_i64[0];
        v42 = input_user_2;
        goto LABEL_77;
      }
    }
    v48 = v75.m128i_i64[0];
    v42 = input_user_2;
    goto LABEL_77;
  }
LABEL_15:
  if ( v70 != s )
    operator delete(v70, *s + 1LL);
  if ( input_user_2 != &n.m128i_u64[1] )
    operator delete(input_user_2, n.m128i_i64[1] + 1);
  return v9;
}
  • Line 235: receive user input

  • Line 318: process received user input

Take a look on sus_func_1

__int64 __fastcall sus_func_1(__int64 a1, int a2, char *input_user)
{
  char *v4; // r12
  char *splitted_input; // rbx
  char *v6; // r13
  __int8 *v7; // r15
  __m128i *v8; // rsi
  void *v9; // rdx
  __m128i *v10; // r15
  unsigned int v11; // r13d
  char *v12; // rbp
  __int64 v13; // r15
  char *v14; // rdi
  char *v15; // r14
  char *v16; // rdi
  char *v17; // rdi
  __m128i *v19; // rdi
  char *v20; // r14
  void *v21; // r13
  __pid_t v22; // eax
  __m128i *v23; // rdi
  const char *v24; // r13
  void *v26[2]; // [rsp+28h] [rbp-168h] BYREF
  __int64 v27; // [rsp+38h] [rbp-158h]
  void *v28[4]; // [rsp+48h] [rbp-148h] BYREF
  void *v29[2]; // [rsp+68h] [rbp-128h] BYREF
  __int64 v30; // [rsp+78h] [rbp-118h]
  char *path[4]; // [rsp+88h] [rbp-108h] BYREF
  char *s[4]; // [rsp+A8h] [rbp-E8h] BYREF
  __m128i v33; // [rsp+C8h] [rbp-C8h] BYREF
  __m128i v34; // [rsp+D8h] [rbp-B8h] BYREF
  int v35; // [rsp+E8h] [rbp-A8h]
  void *s2[2]; // [rsp+F8h] [rbp-98h] BYREF
  __m128i si128; // [rsp+108h] [rbp-88h] BYREF
  __m128i v38; // [rsp+118h] [rbp-78h]
  __m128i v39; // [rsp+128h] [rbp-68h]
  __int64 v40; // [rsp+138h] [rbp-58h]
  int v41; // [rsp+140h] [rbp-50h]
  unsigned __int64 v42; // [rsp+150h] [rbp-40h]

  v42 = __readfsqword(0x28u);
  *v26 = 0LL;
  v27 = 0LL;
  split_string(a1, input_user, ' ', v26);       // split by ' '
  v4 = v26[1];
  splitted_input = v26[0];
  if ( v26[0] == v26[1] )
  {
    v11 = 1;
    if ( !v26[0] )
      return v11;
    goto LABEL_31;
  }
  v6 = *(a1 + 524416);
  v7 = *(a1 + 524408);
  s2[0] = &si128;
  v29[0] = v6;
  if ( v6 > 0xF )
  {
    s2[0] = std::string::_M_create(s2, v29, 0LL);
    v19 = s2[0];
    si128.m128i_i64[0] = v29[0];
    goto LABEL_34;
  }
  if ( v6 != &dword_0 + 1 )
  {
    if ( !v6 )
      goto LABEL_5;
    v19 = &si128;
LABEL_34:
    memcpy(v19, v7, v6);
    v6 = v29[0];
    v8 = s2[0];
    goto LABEL_6;
  }
  si128.m128i_i8[0] = *v7;
LABEL_5:
  v8 = &si128;
LABEL_6:
  s2[1] = v6;
  v6[v8] = 0;
  v9 = *(splitted_input + 1);                   // first value
  v10 = s2[0];
  if ( v9 == s2[1] && (!v9 || !memcmp(*splitted_input, s2[0], v9)) )// compare length and values (p455)
  {
    if ( v10 != &si128 )
      operator delete(v10, si128.m128i_i64[0] + 1);
    v11 = 1;
    if ( *(splitted_input + 5) != 0x1ELL )      // second value
      goto LABEL_10;
    if ( compare_string(a1, splitted_input + 4)
      && compare_and_md5(a1, splitted_input + 4)
      && compare_string_2(a1, splitted_input + 4)
      && compare_and_md5_2(a1, splitted_input + 4) )
    {
      v41 = 0x200000C9;
      *s2 = _mm_load_si128(&xmmword_14680);
      v40 = 0x9FFFFF3C7FFFFF3ALL;
      si128 = _mm_load_si128(&xmmword_14690);
      v38 = _mm_load_si128(&xmmword_146A0);
      v39 = _mm_load_si128(&xmmword_146B0);
      sub_5DA0(v29, s2, 19LL);
      get_string(s, v29);                       // string enjoy
      v20 = s[0];
      v33.m128i_i64[0] = &v34;
      if ( !s[0] )
        std::__throw_logic_error("basic_string: construction from null is not valid");
      v28[0] = strlen(s[0]);
      v21 = v28[0];
      if ( v28[0] > &byte_9[6] )
      {
        v33.m128i_i64[0] = std::string::_M_create(&v33, v28, 0LL);
        v23 = v33.m128i_i64[0];
        v34.m128i_i64[0] = v28[0];
      }
      else
      {
        if ( v28[0] == &dword_0 + 1 )
        {
          v34.m128i_i8[0] = *v20;
LABEL_50:
          v33.m128i_i64[1] = v28[0];
          *(v28[0] + v33.m128i_i64[0]) = 0;
          sub_61D0(a2);
          std::string::_M_dispose(&v33);
          std::string::_M_dispose(s);
          if ( v29[0] )
            operator delete(v29[0], v30 - v29[0]);
          v22 = fork();
          if ( !v22 )
          {
            close(*a1);
            dup2(a2, 0);
            dup2(a2, 1);
            dup2(a2, 2);
            v38.m128i_i32[0] = 1610612933;
            *s2 = _mm_load_si128(&xmmword_146C0);
            si128 = _mm_load_si128(&xmmword_146D0);
            sub_5DA0(v29, s2, 9LL);
            get_string(s, v29);
            v35 = 1610612933;
            v24 = s[0];
            v33 = _mm_load_si128(&xmmword_146C0);
            v34 = _mm_load_si128(&xmmword_146D0);
            sub_5DA0(v28, &v33, 9LL);
            get_string(path, v28);
            execl(path[0], v24, 0LL);
            std::string::_M_dispose(path);
            if ( v28[0] )
              operator delete(v28[0], v28[2] - v28[0]);
            std::string::_M_dispose(s);
            if ( v29[0] )
              operator delete(v29[0], v30 - v29[0]);
            exit(0);
          }
          v11 = 0;
          if ( v22 < 0 )
            exit(1);
          goto LABEL_10;
        }
        if ( !v28[0] )
          goto LABEL_50;
        v23 = &v34;
      }
      memcpy(v23, v20, v21);
      goto LABEL_50;
    }
  }
  else if ( v10 != &si128 )
  {
    operator delete(v10, si128.m128i_i64[0] + 1);
  }
  v11 = 1;
LABEL_10:
  v12 = splitted_input;
  v13 = (((v4 - splitted_input - 32) >> 5) + 1) & 3;
  if ( ((((v4 - splitted_input - 32) >> 5) + 1) & 3) == 0 )
    goto LABEL_69;
  if ( v13 != 1 )
  {
    if ( v13 != 2 )
    {
      if ( *splitted_input != splitted_input + 16 )
        operator delete(*splitted_input, *(splitted_input + 2) + 1LL);
      v12 = splitted_input + 32;
    }
    if ( *v12 != v12 + 16 )
      operator delete(*v12, *(v12 + 2) + 1LL);
    v12 += 32;
  }
  if ( *v12 != v12 + 16 )
    operator delete(*v12, *(v12 + 2) + 1LL);
  v12 += 32;
  if ( v4 != v12 )
  {
LABEL_69:
    do
    {
      if ( *v12 != v12 + 16 )
        operator delete(*v12, *(v12 + 2) + 1LL);
      v14 = *(v12 + 4);
      v15 = v12 + 32;
      if ( v14 != v12 + 48 )
        operator delete(v14, *(v12 + 6) + 1LL);
      v16 = *(v12 + 8);
      if ( v16 != v12 + 80 )
        operator delete(v16, *(v12 + 10) + 1LL);
      v17 = *(v12 + 12);
      if ( v17 != v12 + 112 )
        operator delete(v17, *(v12 + 14) + 1LL);
      v12 += 128;
    }
    while ( v4 != v15 + 96 );
  }
LABEL_31:
  operator delete(splitted_input, v27 - splitted_input);
  return v11;
}
  • Line 84: compare "p455" with first value on splitted input

  • Line 91-94: compare second value on splitted input with some character and hash

    • all the hash are available on online database because it only a few character

    • sub_DEB0 == md5

So basically we can find all the valid values by set breakpoint on all cmp instruction. For example

pie b 0x6CE8
pie b 0x6E45
pie b 0x75B7
...

During the competition i create gdb script to automate the repetitive task.

#!/usr/bin/python3

class SolverEquation(gdb.Command):
    def __init__ (self):
        super (SolverEquation, self).__init__ ("solve-equation",gdb.COMMAND_OBSCURE)

    def invoke (self, arg, from_tty):
        gdb.execute("pie del")
        
        gdb.execute("set environment OGP=123456")
        gdb.execute("pie b 0x41f1")
        gdb.execute("pie b 0x5175") # anti debug 1
        # gdb.execute("pie b 0x531C") # compare OGP LENGTH
        gdb.execute("pie b 0x41FC") # check success run func_1
        gdb.execute("pie b 0x45f5") # call fork
        gdb.execute("pie b 0x46F3") # call func_3
        gdb.execute("pie b 0xBE09") # anti debug 1
        gdb.execute("pie b 0xBED5") # strlen

        
        gdb.execute("pie run")
        gdb.execute("c")

        gdb.execute("set $al=0x0") # bypass anti debug 1
        gdb.execute("c")

        gdb.execute("c")

        gdb.execute("set follow-fork-mode child")
        gdb.execute("c")
        
def addr2num(addr):
    try:
        return int(addr)  # Python 3
    except:
        return long(addr) # Python 2
SolverEquation()

After get the valid input, just send it to the server and got the shell

from pwn import *

# context.log_level = 'debug'
# r = remote("127.0.0.1", 50009)
r = remote("20.80.240.190", 1235)
r.recvuntil(b">> ")

payload = b"p455 eO23410239a3adefing3k0mn00q666\n"
r.send(payload)
r.interactive()

Flag: AKASEC{Orgalor6_1n_d1sgu1s3_as_d4em0n_p3ngu1n}

Last updated