Search code examples
linuxassemblyx86shellcode

Assembly/Shellcode getting system (host)name


So, for a course in school we are trying to find an assembly code which would find the system hostname (i.e. what's printed out when running "hostname" or "uname -n" in the terminal).

But after a lot of googling, we are stuck. The thing is, the code is then to be converted to shellcode, but with all the versions we've tried it results in segmentation fault. Usually we've written a small C program, assembled it and then using gdb written it into shellcode.

And we always end up with segmentation errors.

So, any suggetions as to how, as simply as possible, find the system hostname through assembly? (Running Ubuntu x86 through VirtualBox)

And secondly, any ideas how to errorcheck current shellcode which results in segmentation fault? (Running executable code from the stack is enabled)

Thanks a lot in advance, with either problem!


Solution

  • The "new uname" syscall returns following structure:

    #define __NEW_UTS_LEN 64
    
    struct new_utsname {
            char sysname[__NEW_UTS_LEN + 1];
            char nodename[__NEW_UTS_LEN + 1];
            char release[__NEW_UTS_LEN + 1];
            char version[__NEW_UTS_LEN + 1];
            char machine[__NEW_UTS_LEN + 1];
            char domainname[__NEW_UTS_LEN + 1];
    };
    

    That means we need to allocate at least 390 bytes for the struct and the nodename begins at offset 65. On 32 bit linux the uname syscall is #122. As such the standalone code could look like:

    xor %eax, %eax              # eax=0
    sub $122, %eax              # eax=-sys_uname
    lea (%esp, %eax, 4), %esp   # allocate buffer
    neg %eax                    # fix sign of sys_uname
    mov %esp, %ebx              # address of the buffer
    int $0x80                   # syscall
    mov $4, %al                 # sys_write (assume eax==0)
    lea -3(%eax), %ebx          # stdout (1)
    lea 65(%esp), %ecx          # address of nodename
    lea 60(%eax), %edx          # length (do strlen if you want)
    int $0x80                   # syscall
    mov $1, %al                 # sys_exit
    int $0x80                   # syscall
    

    This will print the whole nodename, so includes a bunch of trailing zeroes (which are normally not visible). Determining the exact string length is left as an exercise ;)

    This is position independent (and zero byte free) code, just getting the machine code bytes and copying it into the stack should make it work as shellcode (assuming executable stack as you said):

    void main()
    {
        char code[] = {
            0x31, 0xc0, 0x83, 0xe8, 0x7a, 0x8d, 0x24, 0x84,
            0xf7, 0xd8, 0x89, 0xe3, 0xcd, 0x80, 0xb0, 0x04,
            0x8d, 0x58, 0xfd, 0x8d, 0x4c, 0x24, 0x41, 0x8d,
            0x50, 0x3c, 0xcd, 0x80, 0xb0, 0x01, 0xcd, 0x80 };
        ((void(*)())code)();
    }
    

    Compile using gcc -m32 -z execstack.