This one was a quite easy one. Using radare let’s find more information about the binary:

 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
$ r2 -AA 88eb31060c4abd0931878bf7d2dd8c1a

[0x08048380]> iI
havecode true
pic      false
canary   false
nx       true
crypto   false
va       true
intrp    /lib/ld-linux.so.2
bintype  elf
class    ELF32
lang     c
arch     x86
bits     32
machine  Intel 80386
os       linux
minopsz  1
maxopsz  16
pcalign  0
subsys   linux
endian   little
stripped false
static   false
linenum  true
lsyms    true
relocs   true
rpath    NONE
binsz    7450

Ok, now let’s have a look at the entry point:

 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
[0x08048380]> pdf @ sym.main
;-- main:
/ (fcn) sym.main 231
   sym.main ();
           ; var int local_4h_2 @ ebp-0x4
           ; var int local_4h @ esp+0x4
           ; var int local_8h @ esp+0x8
           ; var int local_1ch @ esp+0x1c
           ; arg int arg_2ch @ esp+0x2c
           ; JMP XREF from 0x08048397 (entry0)
           ; DATA XREF from 0x08048397 (entry0)
           0x0804846c      55             push ebp
           0x0804846d      89e5           mov ebp, esp
           0x0804846f      57             push edi
           0x08048470      83e4f0         and esp, 0xfffffff0
           0x08048473      83ec30         sub esp, 0x30               ; '0'
           0x08048476      c744242c0000.  mov dword [esp + arg_2ch], 0
           0x0804847e      c70424180000.  mov dword [esp], 0x18       ; [0x18:4]=0x8048380 sym._start
           0x08048485      e8a6feffff     call sym.imp.malloc        ;  void *malloc(size_t size);
           0x0804848a      8944242c       mov dword [esp + arg_2ch], eax
           0x0804848e      c74424081800.  mov dword [esp + local_8h], 0x18 ; [0x18:4]=0x8048380 sym._start
           0x08048496      c74424040000.  mov dword [esp + local_4h], 0
           0x0804849e      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484a2      890424         mov dword [esp], eax
           0x080484a5      e8c6feffff     call sym.imp.memset
           0x080484aa      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484ae      c700464c4147   mov dword [eax], 0x47414c46 ; [0x47414c46:4]=-1
           0x080484b4      c740042d3430.  mov dword [eax + 4], 0x3930342d ; [0x3930342d:4]=-1
           0x080484bb      66c740083200   mov word [eax + 8], 0x32    ; '2' ; [0x32:2]=27 ; '2'
           0x080484c1      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484c5      c744241cffff.  mov dword [esp + local_1ch], 0xffffffff ; [0xffffffff:4]=-1 LEA edi ; edi
           0x080484cd      89c2           mov edx, eax
           0x080484cf      b800000000     mov eax, 0
           0x080484d4      8b4c241c       mov ecx, dword [esp + local_1ch] ; [0x1c:4]=52
           0x080484d8      89d7           mov edi, edx
           0x080484da      f2ae           repne scasb al, byte es:[edi]
           0x080484dc      89c8           mov eax, ecx
           0x080484de      f7d0           not eax
           0x080484e0      8d50ff         lea edx, [eax - 1]
           0x080484e3      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484e7      01d0           add eax, edx
           0x080484e9      c70038343975   mov dword [eax], 0x75393438 ; [0x75393438:4]=-1
           0x080484ef      c74004696f32.  mov dword [eax + 4], 0x6a326f69 ; [0x6a326f69:4]=-1
           0x080484f6      66c740086600   mov word [eax + 8], 0x66    ; 'f' ; [0x66:2]=0 ; 'f'
           0x080484fc      c70424f88504.  mov dword [esp], str.Loading... ; [0x80485f8:4]=0x64616f4c LEA str.Loading... ; "Loading..." @ 0x80485f8
           0x08048503      e838feffff     call sym.imp.puts
           0x08048508      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x0804850c      c744241cffff.  mov dword [esp + local_1ch], 0xffffffff ; [0xffffffff:4]=-1 LEA edi ; edi
           0x08048514      89c2           mov edx, eax
           0x08048516      b800000000     mov eax, 0
           0x0804851b      8b4c241c       mov ecx, dword [esp + local_1ch] ; [0x1c:4]=52
           0x0804851f      89d7           mov edi, edx
           0x08048521      f2ae           repne scasb al, byte es:[edi]
           0x08048523      89c8           mov eax, ecx
           0x08048525      f7d0           not eax
           0x08048527      8d50ff         lea edx, [eax - 1]
           0x0804852a      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x0804852e      01d0           add eax, edx
           0x08048530      c7006b6c736a   mov dword [eax], 0x6a736c6b ; [0x6a736c6b:4]=-1
           0x08048536      c74004346b6c.  mov dword [eax + 4], 0x6c6b34 ; [0x6c6b34:4]=-1
           0x0804853d      c70424038604.  mov dword [esp], str.Where_is_the_flag_ ; [0x8048603:4]=0x72656857 LEA str.Where_is_the_flag_ ; "Where is the flag?" @ 0x8048603
           0x08048544      e8f7fdffff     call sym.imp.puts
           0x08048549      b800000000     mov eax, 0
           0x0804854e      8b7dfc         mov edi, dword [ebp - local_4h_2]
           0x08048551      c9             leave
           0x08048552      c3             ret

Indeed, this is a lot of information. Let’s dissect the programm’s flow:

1
2
3
4
5
           0x0804846c      55             push ebp
           0x0804846d      89e5           mov ebp, esp
           0x0804846f      57             push edi
           0x08048470      83e4f0         and esp, 0xfffffff0
           0x08048473      83ec30         sub esp, 0x30               ; '0'

This looks like a function prologue: Save the stack base pointer, allocate additional stack place (0x30).

1
2
3
           0x08048476      c744242c0000.  mov dword [esp + arg_2ch], 0
           0x0804847e      c70424180000.  mov dword [esp], 0x18       ; [0x18:4]=0x8048380 sym._start
           0x08048485      e8a6feffff     call sym.imp.malloc        ;  void *malloc(size_t size);

Allocate some heap using malloc

1
2
3
4
5
6
           0x0804848a      8944242c       mov dword [esp + arg_2ch], eax
           0x0804848e      c74424081800.  mov dword [esp + local_8h], 0x18 ; [0x18:4]=0x8048380 sym._start
           0x08048496      c74424040000.  mov dword [esp + local_4h], 0
           0x0804849e      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484a2      890424         mov dword [esp], eax
           0x080484a5      e8c6feffff     call sym.imp.memset

The syntax for memset looks like this:

1
2
3
4
5
6
7
8
SYNOPSIS
    void *memset(void *s, int c, size_t n);

DESCRIPTION
   The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.

RETURN VALUE
  The memset() function returns a pointer to the memory area s.

Since we’re dealing with x86 (this site is very good) the arguments for memset are being pushed into the stack:

Graphviz code
dot {
	digraph G {
	 
		// Define layout
		graph [pad=".75", ranksep="0.95", nodesep="0.05"];
		rankdir=LR;
		node [shape="record"];
		rank=same;
	 
		// Define pointers
		rsp [
			label="<p> $rsp \l", height="0.1",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
		rbp [
			label="<p> $rbp \l", height="0.1",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
	 
		rsp_4 [
			label="<p> $rsp + 4 \l", height="0.01",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
	 
	 
		rsp_8 [
			label="<p> $rsp + 8 \l", height="0.01",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white,
		];
	 
		// rsp_12 [
		// 	label="<p> $rsp + 12 \l", height="0.01",
		// 	color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white,
		// ];
	 
		// Define stack
		stack [
			width="3",
			label="<p>\nStack\n\n | <bp>\n...\n\n | <8>0x8 \l | <4>0x0  \l | <0>pointer to memory allocated by malloc() \l"
		];
	   
	   
		// Pointer -> Stack edges
		rbp:p -> stack:bp [style=dotted];
		rsp:p -> stack:0 [style=dotted];
		rsp_4:p -> stack:4 [style=invis];
		rsp_8:p -> stack:8 [style=invis];
	}
}

stack

So memset will set the value “0” 8 times at the address pointed by eax. Afterwards some values will be moved into the previously allocated memory range:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
           0x080484aa      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484ae      c700464c4147   mov dword [eax], 0x47414c46 ; [0x47414c46:4]=-1
           0x080484b4      c740042d3430.  mov dword [eax + 4], 0x3930342d ; [0x3930342d:4]=-1
           0x080484bb      66c740083200   mov word [eax + 8], 0x32    ; '2' ; [0x32:2]=27 ; '2'
           0x080484c1      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484c5      c744241cffff.  mov dword [esp + local_1ch], 0xffffffff ; [0xffffffff:4]=-1 LEA edi ; edi
           0x080484cd      89c2           mov edx, eax
           0x080484cf      b800000000     mov eax, 0
           0x080484d4      8b4c241c       mov ecx, dword [esp + local_1ch] ; [0x1c:4]=52
           0x080484d8      89d7           mov edi, edx
           0x080484da      f2ae           repne scasb al, byte es:[edi]
           0x080484dc      89c8           mov eax, ecx
           0x080484de      f7d0           not eax
           0x080484e0      8d50ff         lea edx, [eax - 1]
           0x080484e3      8b44242c       mov eax, dword [esp + arg_2ch] ; [0x2c:4]=0x280009 ; ','
           0x080484e7      01d0           add eax, edx
           0x080484e9      c70038343975   mov dword [eax], 0x75393438 ; [0x75393438:4]=-1
           0x080484ef      c74004696f32.  mov dword [eax + 4], 0x6a326f69 ; [0x6a326f69:4]=-1
           0x080484f6      66c740086600   mov word [eax + 8], 0x66    ; 'f' ; [0x66:2]=0 ; 'f'
           0x080484fc      c70424f88504.  mov dword [esp], str.Loading... ; [0x80485f8:4]=0x64616f4c LEA str.Loading... ; "Loading..." @ 0x80485f8

At this point I’ll switch to dynamic analysis and therefore run the code:

1
2
3
4
$ gdb 88eb31060c4abd0931878bf7d2dd8c1a
...
gef> b *0x080484aa
gef> r

Now from 0x080484aa through 0x080484fc you can s (step) the opcodes. Then pay attention to the stack. You should have sth like:

Graphviz code
dot {
	digraph G {
	 
		// Define layout
		graph [pad=".75", ranksep="0.95", nodesep="0.05"];
		rankdir=LR;
		node [shape="record"];
		rank=same;
	 
		// Define pointers
		rsp [
			label="<p> $rsp \l", height="0.1",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
		rbp [
			label="<p> $rbp \l", height="0.1",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
	 
		rsp_4 [
			label="<p> $rsp + 4 \l", height="0.01",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white
		];
	 
	 
		rsp_8 [
			label="<p> $rsp + 8 \l", height="0.01",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white,
		];
	 
		rsp_12 [
			label="<p> $rsp + 12 \l", height="0.01",
			color=white, fontcolor=black,fontsize=9,style=filled, fillcolor=white,
		];
	 
		// Define stack
		stack [
			width="3",
			label="<p>\nStack\n\n | <bp>\n...\n\n | <12>0x080485b2  \l | <8>0x18 \l | <4>0x0  \l | <0>0x0804b008 \l"
		];
	   
		// Define values
		val [
			width="5",color=blue,
			label="<p>\nValues\n\n | \n...\n\n | <1>FLAG-4092849uio2jf \l | <2>(__libc_csu_init+82): add esi,0x1 \l"
		];
	   
	   
		// Pointer -> Stack edges
		rbp:p -> stack:bp [style=dotted];
		rsp:p -> stack:0 [style=dotted];
		rsp_4:p -> stack:4 [style=invis];
		rsp_8:p -> stack:8 [style=invis];
		rsp_12:p -> stack:12 [style=invis];
	 
		// Trick to have everything horizontally aligned
		stack:p -> val:p [style=invis];
	   
		// Stack -> Values edges
		edge[style=dotted];
		stack:0 -> val:1 [color=red];
		stack:12 -> val:2;
	}

stack

Bingo. So the flag is FLAG-4092849uio2jf.