Home ASCWG - rev/Unpacking 1337 [900]
Post
Cancel

ASCWG - rev/Unpacking 1337 [900]

Arab Security Cyber Wargames Qualification

Unpacking 1337

The challenge is an elf file called

1
2
> file Akaza
Akaza: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header

The file is packed and when running it asks for the flag.

unpacking

To unpack it I start by running the binary and then attaching ida debugger then inspect the stack and noticed what could be a return address following this address in hex view found the unpacked elf at address 0x800000000 ![[1.png]]

ida_stack IDA Stack

reverse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
__int64 sub_7AA()
{
  __int64 result; // rax
  int v1; // [rsp+10h] [rbp-880h]
  int v2; // [rsp+14h] [rbp-87Ch]
  int v3; // [rsp+18h] [rbp-878h]
  int i; // [rsp+1Ch] [rbp-874h]
  _DWORD v5[12]; // [rsp+20h] [rbp-870h] BYREF
  _DWORD v6[20]; // [rsp+50h] [rbp-840h] BYREF
  _BYTE v7[208]; // [rsp+A0h] [rbp-7F0h] BYREF
  _BYTE v8[1816]; // [rsp+170h] [rbp-720h] BYREF
  unsigned __int64 v9; // [rsp+888h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  memset(v6, 0, sizeof(v6));
  v1 = 0;
  memset(v5, 0, 40);
  memset(v7, 0, 0xC8uLL);
  qmemcpy(v8, qword_1320, 0x70AuLL);
  v2 = 0;
  v3 = 0;
  sub_640();
  sub_680();
  for ( i = 0; i <= 9; ++i )
  {
    v5[i] = 0;
    v5[i] |= (unsigned __int8)v7[4 * i + 3] << 24;
    v5[i] |= (unsigned __int8)v7[4 * i + 2] << 16;
    v5[i] |= (unsigned __int8)v7[4 * i + 1] << 8;
    v5[i] |= (unsigned __int8)v7[4 * i];
  }
  if ( sub_650() == 40 )
  {
    while ( 2 )
    {
      switch ( v8[v1] )
      {
        case 1:
          v6[(unsigned __int8)v8[v1 + 1]] += (unsigned __int8)v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 2:
          v6[(unsigned __int8)v8[v1 + 1]] -= (unsigned __int8)v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 3:
          v6[(unsigned __int8)v8[v1 + 1]] *= (unsigned __int8)v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 4:
          v6[(unsigned __int8)v8[v1 + 1]] /= (unsigned int)(unsigned __int8)v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 5:
          v6[(unsigned __int8)v8[v1 + 1]] >>= v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 6:
          v6[(unsigned __int8)v8[v1 + 1]] <<= v8[v1 + 2];
          v1 += 3;
          goto LABEL_31;
        case 7:
          v6[(unsigned __int8)v8[v1 + 1]] += v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 8:
          v6[(unsigned __int8)v8[v1 + 1]] -= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 9:
          v6[(unsigned __int8)v8[v1 + 1]] *= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xA:
          v6[(unsigned __int8)v8[v1 + 1]] /= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xB:
          v6[(unsigned __int8)v8[v1 + 1]] >>= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xC:
          v6[(unsigned __int8)v8[v1 + 1]] <<= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xD:
          v6[(unsigned __int8)v8[v1 + 1]] ^= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xE:
          v6[(unsigned __int8)v8[v1 + 1]] &= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0xF:
          v6[(unsigned __int8)v8[v1 + 1]] |= v6[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0x10:
          v6[(unsigned __int8)v8[v1 + 1]] = v5[(unsigned __int8)v8[v1 + 2]];
          v1 += 3;
          goto LABEL_31;
        case 0x11:
          if ( v6[(unsigned __int8)v8[v1 + 1]] == v6[(unsigned __int8)v8[v1 + 2]] )
            ++v3;
          v1 += 3;
          goto LABEL_31;
        case 0x12:
          if ( v3 == 50 )
            sub_670();
          else
            sub_640();
          result = 1LL;
          break;
        default:
          v2 = 1;
LABEL_31:
          if ( !v2 )
            continue;
          result = 1LL;
          break;
      }
      break;
    }
  }
  else
  {
    sub_640();
    result = 1LL;
  }
  if ( __readfsqword(0x28u) != v9 )
    return sub_660();
  return result;
}

when decompiling the unpacked file we still have to reverse this encryption a python z3 script will do the trick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from z3 import *

x0 = BitVec('x0', 32)
x1 = BitVec('x1', 32)
x2 = BitVec('x2', 32)
x3 = BitVec('x3', 32)
x4 = BitVec('x4', 32)
x5 = BitVec('x5', 32)
x6 = BitVec('x6', 32)
x7 = BitVec('x7', 32)
x8 = BitVec('x8', 32)
x9 = BitVec('x9', 32)

s = Solver()

s.add(x1 ^ x0 == 1662461958)
s.add(x4 ^ x2 == 83907589)
s.add(x8 + x0 == 2444723369)
s.add(x4 & x0 == 289620800)
s.add(x5 ^ x2 == 1516982324)
s.add(x8 & x7 == 439619872)
s.add(x3 & x7 == 288641811)
s.add(x1 & x1 == 877951815)
s.add(x1 + x8 == 1858645167)
s.add(x9 & x3 == 824254729)
s.add(x1 | x4 == 895450991)
s.add(x8 & x5 == 708059464)
s.add(x1 | x5 == 2121562975)
s.add(x4 & x1 == 810836806)
s.add(x8 | x9 == 2138386793)
s.add(x8 | x8 == 980693352)
s.add(x3 + x9 == 2929235080)
s.add(x8 ^ x6 == 1363166519)
s.add(x9 & x0 == 1426129153)
s.add(x3 ^ x2 == 86523956)
s.add(x9 + x8 == 3080016529)
s.add(x1 ^ x6 == 1600130840)
s.add(x2 & x8 == 810824040)
s.add(x3 ^ x1 == 86181912)
s.add(x5 ^ x0 == 964112414)
s.add(x7 + x6 == 3395867538)
s.add(x9 & x8 == 941629736)
s.add(x3 | x9 == 2104980351)
s.add(x2 + x6 == 2677254090)
s.add(x3 + x2 == 1708566218)
s.add(x6 & x4 == 554984526)
s.add(x8 & x9 == 941629736)
s.add(x1 | x7 == 2138341239)
s.add(x6 | x5 == 1865709407)
s.add(x2 + x3 == 1708566218)
s.add(x8 ^ x2 == 237699587)
s.add(x6 ^ x9 == 370496886)
s.add(x5 ^ x0 == 964112414)
s.add(x5 ^ x4 == 1600848945)
s.add(x9 ^ x8 == 1196757057)
s.add(x2 & x0 == 339940161)
s.add(x1 ^ x2 == 739372)
s.add(x8 ^ x7 == 1698721371)
s.add(x2 + x3 == 1708566218)
s.add(x3 | x9 == 2104980351)
s.add(x3 | x8 == 997684095)
s.add(x4 ^ x2 == 83907589)
s.add(x7 & x8 == 439619872)
s.add(x5 | x6 == 1865709407)
s.add(x5 & x6 == 1781817439)

print(s.model())

1
2
3
4
5
6
7
8
9
10
[x9 = 2099323177,
x4 = 828335982,
x5 = 1848927071,
x6 = 1798599775,
x7 = 1597267763,
x3 = 829911903,
x2 = 878654315,
x8 = 980693352,
x1 = 877951815,
x0 = 1464030017]

convert bytes to chars and reorder them

flag ASCWG{T4k3_4_sw1ng_1_c4n_t4k3_4_h1t:)!!}

This post is licensed under CC BY 4.0 by the author.