digitalXmage
digitalXmage

Reputation: 147

How to Compile a C program which contains 32bit asm into .o file?

Introduction

I'm following through the book "Learning Linux Binary Analysis". I have some experience working with 32 bit assembly and C (however still consider myself a novice). However I'm having trouble and confusion of how to compile a c program , which contains 32 bit assembly into an object file .o. So im guessing this is just a compilation issue on my part.

The Source code is for part of an example of code injection-based binary patching.

Source Code

#include <sys/syscall.h>
int _write (int fd, void *buf, int count)
{
  long ret;
  __asm__ __volatile__ ("pushl %%ebx\n\t"
  "movl %%esi,%%ebx\n\t"
  "int $0x80\n\t""popl %%ebx":"=a" (ret)
                          :"0" (SYS_write), "S" ((long) fd),
  "c" ((long) buf), "d" ((long) count));
    if (ret >= 0) {
        return (int) ret;
 }
 return -1;
}
int evil_puts(void)
{
        _write(1, "HAHA puts() has been hijacked!\n", 31);
}

The problem

I attempt to compile evil_puts.c into .o file. Which will then be used later for injection into another simple program.

gcc -c evil_puts.c

evil_puts.c: Assembler messages:

evil_puts.c:5: Error: invalid instruction suffix for `push'

evil_puts.c:8: Error: invalid instruction suffix for `pop'

I've received this before when working with 32 assembly with gas. And to solve this i put the '-32' flag when compiling and linking. Which i'm guessing is the problem? however not completely sure, and don't have an idea of how to compile it in 32 bit with C and gcc if that's the case?

I also attempted to change it to 64bit to see if it would work, by replacing 'l' of every command to 'q' and changing the registers to begin with 'r'. which seems to work. However the book uses 32 bit. So i wish to keep it that way. Any ideas? Sorry if this is a really basic question.

Also tried '-m32' but receive this:

fatal error: sys/syscall.h: No such file or directory

Upvotes: 1

Views: 945

Answers (2)

o11c
o11c

Reputation: 16076

Knowledge specific to 32-bit x86 is of limited usefulness these days since basically everybody has switched to 64-bit (this is a good thing - 32-bit has a lot of register pressure and address space pressure).

Luckily, you don't actually need any asm for what you're doing. I've also made a couple sanity fixes:

#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>

#define write_str(fd, s) my_write(fd, s, strlen(s))
static ssize_t my_write(int fd, const void *buf, size_t count)
{
    return syscall(SYS_write, (long)fd, (long)buf, (long)count);
}

int puts(const char *s __attribute__((unused)))
{
    write_str(STDOUT_FILENO, "HAHA puts() has been hijacked!\n");
    return strlen(s) + 1;
}

I'm not sure exactly why you're avoiding write(2). But if you really need to avoid syscall(2) as well, it will still be far easier to implement that single function in assembly than write assembly everywhere.

Upvotes: 1

Wyllow Wulf
Wyllow Wulf

Reputation: 410

Use gcc -m32 -c evil_puts.c -o evil_puts.o

You're getting that error because you don't have the 32-bit libraries installed.

If using Ubuntu:

sudo apt-get install gcc-multilib

Upvotes: 3

Related Questions