The Ricardo Narvaja’s challenge aims to learn about IDA Pro, and use it as much as possible. The challenge can be found here and I modified the IDB for a better understanding.

This challenge interacts with a file called fichero.dat, read and store in local variables (struct). Since is a small file, I can infer that there is a buffer overflow vulnerability  on stack in that struct (created in the IDB for me).

I’ll show the main pseudocode.

byte_to_read must be less or equal than max_size, that comparison is interesting because if byte_to_read is a negative number, the condition is met and it continues executing, so if I see the vul_fun function, I can see it is used for reading the file fichero.dat.

So, if I write in byte_to_read the number -1 (0xFF) it will cause a buffer overflow on stack based, but first it needs to bypass all checks in the code. In that function, there is a check, it verifies whether cookie2 is equal 1162233672 (0x45464748). In the epilogue there is also a function called check_bytes_reads which aim is checking whether the bytes read  in vul_func are 0x64 bytes.

The bytes reading wich causes a buffer overflow is limited to 0x64 bytes. Now, there is another check  in main.

In this case the system pointer is stored in p_system field, it’s not necessary bypass it, but I think in the next challenges could be necessary for exploitation.

So, with the next three lines and the 64 bytes reading after those bytes, I can bypass all checks.


In the local variable main function.

The size of mi_estructura.buffer is 0x30 bytes, + 0xC bytes = return address. So, it reads 0x64 – 0x28 = 0x3C bytes, I can overwrite the return address.


Now I have made the ROP, but if I look at the stack, there are only 28 bytes, and it needs first an stack pivot. How? Using mnemonics such as: sub esp, r32; xchg esp, r32; etc. In this case, the unique option is sub esp, r32, because I don’t have the stack virtual address.

I try using

Later, I used the IDA string search functionality (it’s necessary searching with spaces between the mnemonic and operands).

And I found only one gadget for stack pivoting at 0x10101A28, but there are another mnemonics in the middle, then I have to keep it in mind using that gadget.

But. Why  no gadget was found using mona or idasploiter?

If I assemble “sub esp, eax” in mona:

And, the gadget.

Again. Why? Ask processor designers hehe.

There many opcodes for the same instruction, in this case, the opcode 2b e0 and 29 c4, is sub esp, eax.

This gadget is awful, I need first initialize any register for survive in the execution.

I have:

  • A stack pivot, setting EAX for that purpose.
  • Four PUSH with EBX, ESI, EDI, and EAX which modified stack and the stack pivot.
  • Operation with the EBP content, where EBP register is an address memory.
  • The last PUSH (push dword ptr [ebp-8]), is the current return address.

I will:

  • Set EAX for the stack pivot. The stack point at rop chain (start of buffer).
  • Set EBP with an address memory valid.
  • Set [EBP-8], with memory address valid, which get the three push (see the instructions from 0x10101A2B to 10101A2c and 0x10101A37), and again the stack point at rop chain.

The stack should look like this.

When the last gadget is executed, the  push dword ptr [ebp-8] instruction contains another gadget (0x10101092) which cleans the stack . Finally the stack points to the buffer start.

So, I need to write into that buffer another ropchain for executing a calc.

The gadget at 0x101013B8 is in _start, that mean calc execution loop, because main is called from _start function. If I use the gadget at 0x101019C5, the calc will execute only once.

Another interesting point here is the CFG in the two gadgets. For example:

In this case, CFG is disabled. Why? I quote from MSDN.

This feature is available in Microsoft Visual Studio 2015, and runs on “CFG-Aware” versions of Windows—the x86 and x64 releases for Desktop and Server of Windows 10 and Windows 8.1 Update (KB3000850).

And… executing the exploit! 😀

PD: I used w7 x86.

Noxi !