Skip to content

Latest commit

 

History

History
374 lines (328 loc) · 13.5 KB

247ctf.md

File metadata and controls

374 lines (328 loc) · 13.5 KB

247/CTF - Reverse Engineering solutions

https://247ctf.com

The More the Merrier

Disassembly of main:

push    rbp
mov     rbp, rsp
sub     rsp, 10h
lea     rax, unk_6E8
mov     [rbp+var_8], rax
lea     rdi, s          ; "Nothing to see here.."
call    _puts
mov     eax, 0
leave
retn

Before puts is called, we see an address 0x6e8 being stored in rax. If we go to the address we find the flag characters separated by several bytes (due to which we won't be able to find it using strings).

0x6E8 unk_6E8         db  32h ; 2             ; DATA XREF: main+8↑o
0x6E9                 db    0
0x6EA                 db    0
0x6EB                 db    0
0x6EC                 db  34h ; 4
0x6ED                 db    0
0x6EE                 db    0
0x6EF                 db    0
0x6F0                 db  37h ; 7
0x6F1                 db    0
0x6F2                 db    0
0x6F3                 db    0
0x6F4                 db  43h ; C
0x6F5                 db    0
0x6F6                 db    0
0x6F7                 db    0
0x6F8                 db  54h ; T

Flag: 247CTF{6df215eb3cc73407267031a15b0ab36c}

The Encrypted Password

On decompiling the main function in IDA, we see that a strings of ASCII encoded hex characters are being XORed with some data stored on the stack.

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int i; // [rsp+8h] [rbp-A8h]
  int j; // [rsp+Ch] [rbp-A4h]
  char s[48]; // [rsp+10h] [rbp-A0h]
  char s2[8]; // [rsp+40h] [rbp-70h]
  __int64 v8; // [rsp+48h] [rbp-68h]
  __int64 v9; // [rsp+50h] [rbp-60h]
  __int64 v10; // [rsp+58h] [rbp-58h]
  char v11; // [rsp+60h] [rbp-50h]
  char s1[40]; // [rsp+70h] [rbp-40h]
  unsigned __int64 v13; // [rsp+98h] [rbp-18h]

  v13 = __readfsqword(0x28u);
  strcpy(s, "875e9409f9811ba8560beee6fb0c77d2");
  *(_QWORD *)s2 = 0x5A53010106040309LL;
  v8 = 0x5C585354500A5B00LL;
  v9 = 0x555157570108520DLL;
  v10 = 0x5707530453040752LL;
  v11 = 0;
  for ( i = 0; i < strlen(s); ++i )
    s2[i] ^= s[i];
  puts("Enter the secret password:");
  fgets(s1, 33, stdin);
  if ( !strcmp(s1, s2) )
    printf("You found the flag!\n247CTF{%s}\n", s2);
  for ( j = 0; j < strlen(s); ++j )
    s2[j] = 0;
  return 0LL;
}

Here is a script that emulates the above code to get the flag.

from pwn import *
p = make_packer('all')

h = p(0x5A53010106040309)
h += p(0x5C585354500A5B00)
h += p(0x555157570108520D)
h += p(0x5707530453040752)

s = '875e9409f9811ba8560beee6fb0c77d2'
ans = ''

for x,y in zip(s,h):
    ans += chr(ord(x) ^ y)

print('247CTF{%s}' % ans)

Flag: 247CTF{141c85ccfb2ae19d8d8c224c4e403dce}

The Flag Bootloader

Here we have an MS-DOS executable. We can go into any dissassembler of our choice and see how the program works. At the offset 0x23 we get the flag verification code and reading through the assembly, I came up with the following script to get the flag.

si = [0x77, 0x21, 0x67, 0x30, 0x60, 0x35, 0x0c, 0x0c, 0x78, 0x79, 0x2e, \
      0x2e, 0x20, 0x72, 0x70, 0x75, 0x29, 0x2b, 0x00, 0x5c, 0x21, 0x70, \
      0x62, 0x63, 0x65, 0x60, 0x07, 0x0d, 0x06, 0x02, 0x3b, 0x3b]

def xs(al,si,c):
    si[c] ^= al
    si[c+1] ^= al
    return c+2

c = 0
c = xs(0x4b^0x0c,si,c)
c = xs(0x53^0x06,si,c)
c = xs(0x58-0x01,si,c)
c = xs(0x62-0x29,si,c)
c = xs(0x68^0x23,si,c)
c = xs(0x4b^0x00,si,c)
c = xs(0x62-0x1e,si,c)
c = xs(0x4d-0x0b,si,c)
c = xs(0x45^0x0d,si,c)
c = xs(0x10^0x28,si,c)
c = xs(0x58^0x1d,si,c)
c = xs(0x7a^0x28,si,c)
c = xs(0x65-0x13,si,c)
c = xs(0x33^0x07,si,c)
c = xs(0x25^0x15,si,c)
c = xs(0x4c+0x0c,si,c)

flag = ''
for i in si:
    flag += chr(i)
print('247CTF{%s}' % flag)

Flag: 247CTF{0f2e7b5532eed627ac8dd501723962cc}

The Secret Lock

In this challenge we are given a webpage where we have to submit the flag that is then verified by javascript in the checkFlag function which has a long list of equations to be satisfied.

checkFlag(flag){
  let result = "LOCKED"
  this.dom.lock.classList.remove('verified');
  if (Object.keys(flag).length == 40 &&
        ((flag[37] - flag[37]) * flag[15] == 0) &&
        ((flag[3] + flag[31]) ^ ...) {
    result = "";
    for (var idx in flag) {
      result += (String.fromCharCode(flag[idx]));
    }
    this.dom.lock.classList.add('verified');
  }
  return result;
}

So I decided to use the z3-solver package in python to solve the equations.

from z3 import *

flag = [
    BitVec("flag[0]", 8), BitVec("flag[1]", 8), BitVec("flag[2]", 8),
    BitVec("flag[3]", 8), BitVec("flag[4]", 8), BitVec("flag[5]", 8),
    BitVec("flag[6]", 8), BitVec("flag[7]", 8), BitVec("flag[8]", 8),
    BitVec("flag[9]", 8), BitVec("flag[10]", 8), BitVec("flag[11]", 8),
    BitVec("flag[12]", 8), BitVec("flag[13]", 8), BitVec("flag[14]", 8),
    BitVec("flag[15]", 8), BitVec("flag[16]", 8), BitVec("flag[17]", 8),
    BitVec("flag[18]", 8), BitVec("flag[19]", 8), BitVec("flag[20]", 8),
    BitVec("flag[21]", 8), BitVec("flag[22]", 8), BitVec("flag[23]", 8), 
    BitVec("flag[24]", 8), BitVec("flag[25]", 8), BitVec("flag[26]", 8),
    BitVec("flag[27]", 8), BitVec("flag[28]", 8), BitVec("flag[29]", 8),
    BitVec("flag[30]", 8), BitVec("flag[31]", 8), BitVec("flag[32]", 8),
    BitVec("flag[33]", 8), BitVec("flag[34]", 8), BitVec("flag[35]", 8),
    BitVec("flag[36]", 8), BitVec("flag[37]", 8), BitVec("flag[38]", 8),
    BitVec("flag[39]", 8),
]


s = Solver()
s.add((flag[37] - flag[37]) * flag[15] == 0) 
s.add((flag[3] + flag[31]) ^ (flag[29] + flag[8]) == 234) 
s.add((flag[32] - flag[12]) * flag[9] == -2332) 
s.add((flag[24] - flag[27] + flag[13]) ^ flag[6] == 114) 
s.add((flag[38] - flag[15]) * flag[33] == 800) 
s.add((flag[34] - flag[21]) * flag[26] == 98) 
s.add((flag[29] + flag[0]) ^ (flag[8] + flag[38]) == 248) 
s.add((flag[21] * flag[18]) ^ (flag[7] - flag[15]) == 2694) 
s.add((flag[28] * flag[23]) ^ (flag[19] - flag[5]) == -9813) 
s.add((flag[34] + flag[30]) ^ (flag[37] + flag[6]) == 72) 
s.add((flag[23] - flag[22]) * flag[12] == 4950) 
s.add((flag[9] * flag[28]) ^ (flag[20] - flag[11]) == 5143) 
s.add((flag[2] * flag[22]) ^ (flag[37] - flag[0]) == 2759) 
s.add((flag[26] - flag[12]) * flag[3] == -3350) 
s.add((flag[35] * flag[0]) ^ (flag[23] - flag[21]) == 2698) 
s.add((flag[20] + flag[31]) ^ (flag[5] + flag[10]) == 22) 
s.add((flag[31] * flag[19]) ^ (flag[1] - flag[2]) == -2655) 
s.add((flag[38] - flag[14]) * flag[18] == 55) 
s.add((flag[29] - flag[19] + flag[10]) ^ flag[2] == 93) 
s.add((flag[13] - flag[25] + flag[30]) ^ flag[29] == 13) 
s.add((flag[35] + flag[33]) ^ (flag[26] + flag[21]) == 249) 
s.add((flag[17] + flag[24]) ^ (flag[34] + flag[1]) == 253) 
s.add((flag[32] - flag[35] + flag[19]) ^ flag[1] == 0) 
s.add((flag[22] - flag[11] + flag[3]) ^ flag[31] == 113) 
s.add((flag[19] - flag[0]) * flag[13] == 108) 
s.add((flag[19] - flag[17]) * flag[14] == -2475) 
s.add((flag[31] - flag[35] + flag[16]) ^ flag[19] == 84) 
s.add((flag[24] * flag[27]) ^ (flag[35] - flag[17]) == -5792) 
s.add((flag[11] * flag[35]) ^ (flag[15] - flag[28]) == -2845) 
s.add((flag[18] - flag[19] + flag[31]) ^ flag[5] == 112) 
s.add((flag[20] - flag[6]) * flag[10] == -3933) 
s.add((flag[39] - flag[33]) * flag[6] == 3075) 
s.add((flag[22] + flag[1]) ^ (flag[39] + flag[14]) == 211) 
s.add((flag[37] * flag[24]) ^ (flag[12] - flag[39]) == -5726) 
s.add((flag[29] + flag[3]) ^ (flag[8] + flag[11]) == 195) 
s.add((flag[26] * flag[7]) ^ (flag[10] - flag[17]) == -2375) 
s.add((flag[11] - flag[12]) * flag[12] == -4653) 
s.add((flag[13] * flag[5]) ^ (flag[12] - flag[25]) == 3829) 
s.add((flag[24] * flag[0]) ^ (flag[13] - flag[23]) == -2829) 
s.add((flag[17] + flag[12]) ^ (flag[8] + flag[14]) == 170) 
s.add((flag[38] + flag[23]) ^ (flag[11] + flag[1]) == 245) 
s.add((flag[22] + flag[5]) ^ (flag[21] + flag[24]) == 19) 
s.add((flag[35] - flag[8] + flag[21]) ^ flag[30] == 85) 
s.add((flag[18] - flag[31] + flag[28]) ^ flag[29] == 0) 
s.add((flag[30] * flag[35]) ^ (flag[27] - flag[29]) == 5501) 
s.add((flag[8] - flag[30] + flag[16]) ^ flag[36] == 81) 
s.add((flag[13] * flag[18]) ^ (flag[35] - flag[38]) == -2971) 
s.add((flag[27] - flag[14]) * flag[39] == 5875) 
s.add((flag[34] - flag[33]) * flag[6] == -6027) 
s.add((flag[38] * flag[1]) ^ (flag[20] - flag[10]) == -2915) 
s.add((flag[1] - flag[1]) * flag[3] == 0) 
s.add((flag[36] - flag[20]) * flag[8] == 2640) 
s.add((flag[23] - flag[11] + flag[17]) ^ flag[33] == 246) 
s.add((flag[13] - flag[38]) * flag[0] == -100) 
s.add((flag[28] - flag[14]) * flag[31] == 2142) 
s.add((flag[26] + flag[15]) ^ (flag[13] + flag[31]) == 8) 
s.add((flag[36] - flag[15]) * flag[17] == 5238) 
s.add((flag[16] - flag[30]) * flag[33] == 0) 
s.add((flag[2] - flag[20] + flag[13]) ^ flag[6] == 76) 
s.add((flag[10] - flag[14] + flag[31]) ^ flag[13] == 3) 
s.add((flag[0] * flag[10]) ^ (flag[14] - flag[31]) == 2854) 
s.add((flag[28] - flag[34] + flag[14]) ^ flag[14] == 82) 
s.add((flag[28] - flag[25]) * flag[1] == 2444) 
s.add((flag[34] - flag[12]) * flag[25] == -2400) 
s.add((flag[28] * flag[38]) ^ (flag[17] - flag[4]) == 5429) 
s.add((flag[21] - flag[21] + flag[26]) ^ flag[23] == 84) 
s.add((flag[9] - flag[4] + flag[18]) ^ flag[35] == 47) 
s.add((flag[28] - flag[21] + flag[1]) ^ flag[33] == 0) 
s.add((flag[24] - flag[25] + flag[22]) ^ flag[0] == 8) 
s.add((flag[28] - flag[25]) * flag[12] == 4653) 
s.add((flag[1] * flag[15]) ^ (flag[10] - flag[8]) == 2498) 
s.add((flag[5] * flag[7]) ^ (flag[15] - flag[34]) == -3429) 
s.add((flag[8] * flag[3]) ^ (flag[23] - flag[22]) == 3671) 
s.add((flag[25] - flag[33]) * flag[11] == -2600) 
s.add((flag[21] + flag[12]) ^ (flag[37] + flag[28]) == 81) 
s.add((flag[30] + flag[33]) ^ (flag[34] + flag[14]) == 162) 
s.add((flag[6] - flag[25]) * flag[8] == 4015) 
s.add((flag[24] - flag[7] + flag[12]) ^ flag[7] == 90) 
s.add((flag[18] * flag[12]) ^ (flag[8] - flag[4]) == -5466) 
s.add((flag[32] * flag[7]) ^ (flag[32] - flag[27]) == -2730) 
s.add((flag[32] * flag[34]) ^ (flag[29] - flag[16]) == 2804) 
s.add((flag[25] * flag[22]) ^ (flag[28] - flag[39]) == -2542) 
s.add((flag[8] - flag[15]) * flag[6] == 861) 
s.add((flag[20] + flag[18]) ^ (flag[25] + flag[36]) == 245) 
s.add((flag[5] - flag[28] + flag[14]) ^ flag[39] == 97) 
s.add((flag[30] * flag[11]) ^ (flag[16] - flag[11]) == 5216) 
s.add((flag[11] + flag[18]) ^ (flag[7] + flag[9]) == 13) 
s.add((flag[9] - flag[2]) * flag[30] == -200) 
s.add((flag[12] + flag[37]) ^ (flag[9] + flag[4]) == 78) 
s.add((flag[10] - flag[37]) * flag[38] == -2408) 
s.add((flag[5] * flag[19]) ^ (flag[20] - flag[21]) == 3645) 
s.add((flag[27] * flag[29]) ^ (flag[39] - flag[21]) == 10354) 
s.add((flag[15] * flag[32]) ^ (flag[7] - flag[22]) == -2642) 
s.add((flag[1] - flag[3] + flag[24]) ^ flag[31] == 25) 
s.add((flag[13] - flag[0]) * flag[30] == 400) 
s.add((flag[18] - flag[15] + flag[36]) ^ flag[28] == 12) 
s.add((flag[34] + flag[21]) ^ (flag[12] + flag[37]) == 163) 
s.add((flag[36] - flag[33]) * flag[14] == 110) 
s.add((flag[2] - flag[3]) * flag[3] == -804) 
s.add((flag[35] - flag[27] + flag[22]) ^ flag[4] == 80) 
s.add((flag[10] + flag[9]) ^ (flag[17] + flag[2]) == 246) 
s.add((flag[25] * flag[4]) ^ (flag[27] - flag[23]) == 4201) 
s.add((flag[32] * flag[19]) ^ (flag[3] - flag[25]) == 2877) 
s.add((flag[37] - flag[14]) * flag[23] == 4545) 
s.add((flag[32] + flag[13]) ^ (flag[31] + flag[32]) == 7) 
s.add((flag[11] - flag[25]) * flag[39] == 250) 
s.add((flag[17] + flag[31]) ^ (flag[6] + flag[9]) == 36) 
s.add((flag[4] + flag[27]) ^ (flag[2] + flag[31]) == 208) 
s.add((flag[6] + flag[7]) ^ (flag[26] + flag[21]) == 206) 
s.add((flag[19] + flag[25]) ^ (flag[22] + flag[10]) == 10) 
s.add((flag[34] + flag[2]) ^ (flag[8] + flag[26]) == 2) 
s.add((flag[7] + flag[5]) ^ (flag[12] + flag[14]) == 237) 
s.add((flag[1] - flag[13]) * flag[38] == -112) 
s.add((flag[0] - flag[19] + flag[16]) ^ flag[0] == 80) 
s.add((flag[31] + flag[36]) ^ (flag[3] + flag[2]) == 227) 
s.add((flag[32] - flag[3] + flag[26]) ^ flag[4] == 113) 
s.add((flag[3] * flag[6]) ^ (flag[16] - flag[27]) == -8241) 
s.add((flag[24] + flag[15]) ^ (flag[2] + flag[30]) == 242) 
s.add((flag[11] + flag[21]) ^ (flag[31] + flag[20]) == 12) 
s.add((flag[9] - flag[26] + flag[23]) ^ flag[30] == 13)

sol = ''
s.check()
val = s.model()

for i in range(40): sol += chr(val[flag[i]].as_long())
print(sol)

Flag: 247CTF{17594c670da74613e921faed37d37fd8}

Flag Keygen

In this challenge we get a simple ELF64 binary which can be decompiled using IDA. The goal of this challenge is to find of of many product codes, which when entered into the online service will reap us the flag.

The decompiled code in itself is easy to understand. The main function asks us for a 32-bit string of characters in the uppercase ASCII range. It then calls a verification function that depending upon whether the letter comes before or after 'M', keeps a running sum with some other constants. In the end if the sum modulo 248 equals 247, we get the flag.

Below I have scripted the logic for the verification check. After I did that, I got the desired value of 247 through trial and error.

def sub_120A(a1):
    if ord(a1) <= 77: return ord(a1) + 181
    else: return ord(a1) + 177

a1 = 'BBBBBZBBBBBBBBAAAAAAAAAAAAOOOOOO'
# print(sub_120A(a1[0])) # Gives us the first letter ??

v3 = 247
for j in range(1,32):
    v3 += sub_120A(a1[j]) - j + 247

print(v3)
print(v3%248) # Should be 247

Submitting the product code on the socket:

$ nc d19274d14f21d488.247ctf.com 50112
Enter a valid product key to gain access to the flag:
BBBBBZBBBBBBBBAAAAAAAAAAAAOOOOOO
Valid product key!
247CTF{fb88b9fe80e969e73a27541f62d6f89c}