-1

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!

Jester
  • 56,577
  • 4
  • 81
  • 125
  • 1
    Use the debugger to see where it faults. – Jester Nov 29 '15 at 00:25
  • What is "Shellcode"? I think it would help if you include one of your attempts. – asjo Nov 29 '15 at 01:07
  • @Jester , we have tried, it fails at the address of which the shellcode starts, at least with our own current code. – Mattedatten Nov 29 '15 at 01:10
  • @asjo Shellcode, opcode, not sure if it has a set name. It's the instructions of assembly and addresses in hex format, i.e. \x8d\x4c\x24... when used in C, if I've understood it right – Mattedatten Nov 29 '15 at 01:10
  • @Mattedatten yeah, I should have searched for the answer; https://en.wikipedia.org/wiki/Shellcode – asjo Nov 29 '15 at 01:11
  • If it fails right at the start, that means your stack is not executable, contrary to what you think. – Jester Nov 29 '15 at 01:12

1 Answers1

1

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.

Jester
  • 56,577
  • 4
  • 81
  • 125