9447 CTF 2014 - No Strings Attached (Reversing)

3 minute read

A crack me that decrypts the password into a wide length string in memory.

Challenge Description

Points

25

Description

no strings attached (25pts)

Solution

Running the binary yields the following:

$ ./no_strings_attached
Welcome to cyber malware control software.
Currently tracking 2097550375 bots worldwide
Please enter authentication details: AAAAAAAA
Access denied!

Looks like we have to find the correct input to the binary. For 25 points, it should be pretty easy. Let’s take a look at ltrace first though:

$ ltrace ./no_strings_attached
__libc_start_main(0x804876e, 1, 0xffe0eeb4, 0x80487c0 <unfinished ...>
setlocale(LC_ALL, "")                                                                       = "en_SG.UTF-8"
time(0)                                                                                     = 1417538944
srand(0x547ded80, 0xf779c500, 0xffe0ee44, 0xf775c000)                                       = 0
wprintf(0x8048890, 0xf779c500, 0xffe0ee44, 0xf775c000Welcome to cyber malware control software.
)                                      = 43
rand(0x8048890, 0xf779c500, 0xffe0ee44, 0xf775c000)                                         = 0x2dc23a13
wprintf(0x8048940, 0x2dc23a13, 0xffe0ee44, 0xf775c000Currently tracking 767703571 bots worldwide
)                                      = 44
wprintf(0x80489d8, 0x2dc23a13, 0xffe0ee44, 0xf775c000)                                      = 37
wcslen(0x8048a88, 0, 0, 0)                                                                  = 38
wcslen(0x8048a70, 0, 0, 0)                                                                  = 5
wcslen(0x8048a88, 0, 0, 0)                                                                  = 38
malloc(39)                                                                                  = 0x96ef978
wcscpy(0x96ef978, 0x8048a88, 0, 0)                                                          = 0x96ef978
fgetws(0xffe06dec, 8192, 0xf775cc20, 0Please enter authentication details: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
)                                                     = 0xffe06dec
wcslen(0xffe06dec, 8192, 0xf775cc20, 0)                                                     = 42
wcscmp(0xffe06dec, 0x96ef978, 0xf775cc20, 0)                                                = 1
wprintf(0x8048b84, 0x96ef978, 0xf775cc20, 0Access denied!
)                                                = 15
wcslen(0x8048a88, 0x80489d8, 0xffe0ede4, 0xf75e3f14)                                        = 38
wcslen(0x8048a70, 0x80489d8, 0xffe0ede4, 0xf75e3f14)                                        = 5
wcslen(0x8048a88, 0x80489d8, 0xffe0ede4, 0xf75e3f14)                                        = 38
malloc(39)                                                                                  = 0x96ef9a8
wcscpy(0x96ef9a8, 0x8048a88, 0xffe0ede4, 0xf75e3f14)                                        = 0x96ef9a8
+++ exited (status 0) +++

Notice that there are library calls to wcscpy, fgetws, wprintf, wcslen, and wcscmp. These calls are the wide character equivalents of the traditional library calls. So we should expect strings with each character taking up more than 1 byte.

Now for a quick overview of the diassembly:

There are two really interesting functions that stand out at this point: authenticate and decrypt. Let’s look at the CFG for authenticate:

Notice that there is also another call to decrypt. The result of the decryption is then wcscmp’d to a string fgetws’d from the user. We want to discover the result of that particular decryption. For information purposes:

Let’s proceed to the dynamic analysis in GDB.

$ gdb no_strings_attached
GNU gdb (GDB) 7.8
...
Reading symbols from no_strings_attached...(no debugging symbols found)...done.
gdb-peda$ break decrypt
Breakpoint 1 at 0x804862c
gdb-peda$ r
Starting program: /home/amon/ctf2014/9447ctf2014/nsa/no_strings_attached
Welcome to cyber malware control software.
Currently tracking 1332758032 bots worldwide
...
Breakpoint 1, 0x0804862c in decrypt ()
gdb-peda$ fin
Run till exit from #0  0x0804862c in decrypt ()
...
0x080486f5 in authenticate ()

Now, the address of the result from decrypt should be stored in eax. Verifying this by looking at the context:

[----------------------------------registers-----------------------------------]
EAX: 0x804b978 --> 0x39 ('9')
EBX: 0xf7fb0000 --> 0x1abda8
ECX: 0x1480
EDX: 0x7d ('}')
ESI: 0x0
EDI: 0x0
EBP: 0xffffcfa8 --> 0xffffcfc8 --> 0x0
ESP: 0xffff4f80 --> 0x8048a88 --> 0x143a
EIP: 0x80486f5 (<authenticate+29>:    mov    DWORD PTR [ebp-0xc],eax)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x80486e1 <authenticate+9>:    mov    DWORD PTR [esp+0x4],0x8048a70
   0x80486e9 <authenticate+17>:    mov    DWORD PTR [esp],0x8048a88
   0x80486f0 <authenticate+24>:    call   0x8048628 <decrypt>
=> 0x80486f5 <authenticate+29>:    mov    DWORD PTR [ebp-0xc],eax
   0x80486f8 <authenticate+32>:    mov    eax,ds:0x804a038
   0x80486fd <authenticate+37>:    mov    DWORD PTR [esp+0x8],eax
   0x8048701 <authenticate+41>:    mov    DWORD PTR [esp+0x4],0x2000
   0x8048709 <authenticate+49>:    lea    eax,[ebp-0x800c]
[------------------------------------stack-------------------------------------]
0000| 0xffff4f80 --> 0x8048a88 --> 0x143a
0004| 0xffff4f84 --> 0x8048a70 --> 0x1401
0008| 0xffff4f88 --> 0x0
0012| 0xffff4f8c --> 0x0
0016| 0xffff4f90 --> 0x0
0020| 0xffff4f94 --> 0x0
0024| 0xffff4f98 --> 0x0
0028| 0xffff4f9c --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

A ‘9’! That looks super promising. Taking a look at the memory:

gdb-peda$ x/32c 0x804b978
0x804b978:    0x39    0x00    0x00    0x00    0x34    0x00    0x00    0x00
0x804b980:    0x34    0x00    0x00    0x00    0x37    0x00    0x00    0x00
0x804b988:    0x7b    0x00    0x00    0x00    0x79    0x00    0x00    0x00
0x804b990:    0x6f    0x00    0x00    0x00    0x75    0x00    0x00    0x00
gdb-peda$ x/16s 0x804b978
0x804b978:    "9"
0x804b97a:    ""
0x804b97b:    ""
0x804b97c:    "4"
0x804b97e:    ""
0x804b97f:    ""
0x804b980:    "4"
0x804b982:    ""
0x804b983:    ""
0x804b984:    "7"
0x804b986:    ""
0x804b987:    ""
0x804b988:    "{"
0x804b98a:    ""
0x804b98b:    ""
0x804b98c:    "y"

Each character takes up 4 bytes of space. Our short printing of strings revealed a partial flag. Unfortunately, gdb doesn’t have in-built support for wide character strings but we can utilise a function in libc through call.

gdb-peda$ call wprintf($eax)
...
gdb-peda$ fin
Run till exit from #0  0x080486f5 in authenticate ()
Please enter authentication details: 9447{you_are_an_international_mystery}

In addition to the prompt, we have our flag after the prompt is printed :D

Verifying:

$ ./no_strings_attached
Welcome to cyber malware control software.
Currently tracking 2038332618 bots worldwide
Please enter authentication details: 9447{you_are_an_international_mystery}
Success! Welcome back!

Flag: 9447{you_are_an_international_mystery}

Leave a Comment