This question already has answers here:
What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
(1 answer)
How to invoke a system call via syscall or sysenter in inline assembly?
(2 answers)
Closed 8 months ago.
I have a question that has been asked before but comes with an extra caveat. How do I properly execute a GCC inline assembly call given an x86_64 CPU, ubuntu machine, no starter files, and no standard libs? My code compiles with no warnings but does nothing on execution.
I know how to check for syscall numbers on my system, so I am certain I am calling the right number. I am trying to simply write "Hello World" to stdout using this method.
Source:
#define __NR_exit 60
#define __NR_write 1
int sys_exit(int status) {
signed int ret;
asm volatile
(
"int $0x80"
: "=a" (ret)
: "0"(__NR_exit), "b"(status)
: "memory"
);
return ret;
}
int sys_write(int fd, const void *buf, unsigned int count) {
signed int ret;
asm volatile
(
"int $0x80\n\t"
: "=a" (ret)
: "0"(__NR_write), "b"(fd), "c"(buf), "d"(count)
: "memory"
);
return ret;
}
void _start(void){
sys_write(1, "Hello World\0", 11);
sys_exit(0);
}
Comilation:
gcc -nostartfiles -nodefaultlibs -nostdlib hello.c -o hello
Related
This question already has answers here:
Clobber list for rep_movsl
(1 answer)
How to mark as clobbered input operands (C register variables) in extended GCC inline assembly?
(2 answers)
Can I modify input operands in gcc inline assembly
(1 answer)
How can I indicate that the memory *pointed* to by an inline ASM argument may be used?
(1 answer)
Closed 3 months ago.
I try to compile a program as follow:
unsigned long func(int priority)
{
unsigned long a;
if (a)
__asm__ __volatile__("rep ; stosl"
: /* no outputs */ \
:"a" (0),"c" (1024),"D" (page)
:"ecx");
return a;
}
but meet a error:
a.c:6:3: error: ‘asm’ operand has impossible constraints
__asm__ __volatile__("rep ; stosl"
^~~~~~~
by modifying code and compiling again,I find it is "ecx" which causes error
if I delete it,such as
unsigned long func(int priority)
{
unsigned long a;
if (a)
__asm__ __volatile__("rep ; stosl"
: /* no outputs */ \
:"a" (0),"c" (1024),"D" (page)
);
return a;
}
there is no errors
asm allow syntax such as asm("....":output:input:Clobbers),so why my program meet error?
ps:my gcc is gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0,machine is x86-64
This question already has answers here:
What if there is no return statement in a CALLed block of code in assembly programs
(2 answers)
Why is no value returned if a function does not explicity use 'ret'
(2 answers)
Closed 2 years ago.
I've got an assignment in one of my lectures and here I'm stuck right at the beginning.
My ASM file:
.intel_syntax noprefix
.text
.global stuff
stuff:
mov eax, 1
My C file:
#include <stdio.h>
extern int stuff();
int main()
{
int result = stuff();
printf("%d\n", result);
return 0;
}
and I compile with:
gcc -m32 -o runme main.c a.S
Edit:
./runme
prints 0 instead of expected 1. Why is that and how should I fix it?
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
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
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.
This question already has an answer here:
How to embed LLVM assembly or intrinsics in C program with Clang?
(1 answer)
Closed 9 years ago.
I was looking enviously at the ability to put inline assembler in code compiled by GCC, and I'm wondering if you could do something similar with Clang? For example is there some way I could complete the definition of a function with LLVM assembler:
int add_two_ints(int a, int b) {
/*
* some bitcode stuff goes here to add
* the ints and return the result
*/
}
Any references, or code to complete the example above would be great.
clang supports inline assembly, including GCC's extension where you declare input, output, and clobbered registers:
int add_two_ints(int a, int b) {
int result;
asm( "addl %1, %2;"
"movl %2, %0;"
: "=r"(result)
: "r"(a), "r"(b)
:);
return result;
}
Clang also has experimental support for Microsoft's __asm { } syntax and intel style assembly.
It does not have any support for including LLVM-IR in C or C++ source. Such a feature would largely be just a novelty as inline assembly is typically for accessing special instructions and LLVM-IR doesn't enable that.
Somebody over at SO posted a question asking how he could "hide" a function. This was my answer:
#include <stdio.h>
#include <stdlib.h>
int encrypt(void)
{
char *text="Hello World";
asm("push text");
asm("call printf");
return 0;
}
int main(int argc, char *argv[])
{
volatile unsigned char *i=encrypt;
while(*i!=0x00)
*i++^=0xBE;
return EXIT_SUCCESS;
}
but, there are problems:
encode.c: In function `main':
encode.c:13: warning: initialization from incompatible pointer type
C:\DOCUME~1\Aviral\LOCALS~1\Temp/ccYaOZhn.o:encode.c:(.text+0xf): undefined reference to `text'
C:\DOCUME~1\Aviral\LOCALS~1\Temp/ccYaOZhn.o:encode.c:(.text+0x14): undefined reference to `printf'
collect2: ld returned 1 exit status
My first question is why is the inline assembly failing ... what would be the right way to do it? Other thing -- the code for "ret" or "retn" is 0x00 , right... my code xor's stuff until it reaches a return ... so why is it SEGFAULTing?
As a high level point, I'm not quite sure why you're trying to use inline assembly to do a simple call into printf, as all you've done is create an incorrect version of a function call (your inline pushes something onto the stack, but never pop it off, most likely causing problems cause GCC isn't aware that you've modified the stack pointer in the middle of the function. This is fine in a trivial example, but could lead to non-obvious errors in a more complicated function)
Here's a correct implementation of your top function:
int encrypt(void)
{
char *text="Hello World";
char *formatString = "%s\n";
// volatile really isn't necessary but I just use it by habit
asm volatile("pushl %0;\n\t"
"pushl %1;\n\t"
"call printf;\n\t"
"addl $0x8, %%esp\n\t"
:
: "r"(text), "r"(formatString)
);
return 0;
}
As for your last question, the usual opcode for RET is "C3", but there are many variations, have a look at http://pdos.csail.mit.edu/6.828/2009/readings/i386/RET.htm
Your idea of searching for RET is also faulty as due to the fact that when you see the byte 0xC3 in a random set of instructions, it does NOT mean you've encountered a ret. As the 0xC3 may simply be the data/attributes of another instruction (as a side note, it's particularly hard to try and parse x86 instructions as you're doing due to the fact x86 is a CISC architecture with instruction lengths between 1-16 bytes)
As another note, not all OS's allow modification to the text/code segment (Where executable instructions are stored), so the the code you have in main may not work regardless.
GCC inline asm uses AT&T syntax (if no specific options are selected for using Intel's one).
Here's an example:
int a=10, b;
asm ("movl %1, %%eax;
movl %%eax, %0;"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);
Thus, your problem is that "text" is not identifiable from your call (and following instruction too).
See here for reference.
Moreover your code is not portable between 32 and 64 bit environments. Compile it with -m32 flag to ensure proper analysis (GCC will complain anyway if you fall in error).
A complete solution to your problem is on this post on GCC Mailing list.
Here's a snippet:
for ( i = method->args_size - 1; i >= 0; i-- ) {
asm( "pushl %0": /* no outputs */: \
"g" (stack_frame->op_stack[i]) );
}
asm( "call *%0" : /* no outputs */ : "g" (fp) :
"%eax", "%ecx", "%edx", "%cc", "memory" );
asm ( "movl %%eax, %0" : "=g" (ret_value) : /* No inputs */ );
On windows systems there's also an additional asm ( "addl %0, %%esp" : /* No outputs */ : "g" (method->args_size * 4) ); to do. Google for better details.
It is not printf but _printf