I'm trying to print a simple hello world string to the console in inline assembly. My assembly (below) works perfectly fine. I tried translating it into GAS as best as possible but putting the variables into the registers through extended assembly proved rather difficult. From what I can tell, the printmsg function doesn't actually do/print anything.
Assembly:
section .text
global _start
_start:
; Write string to stdout
mov eax, 4
mov ebx, 1
mov ecx, string
mov edx, strlen
int 0x80
; Exit
mov eax, 1
mov ebx, 0
int 0x80
section .data
string db 'Hello, World!',10
strlen equ $ - string
C:
#include <stdio.h>
#include <string.h>
void printmsg(char *msg, int len){
asm( "movl $4, %eax;"
"movl $1, %ebx;"
);
asm( "movl %1, %%ecx;"
"movl %1, %%edx;"
:
: "c" (msg), "d" (len)
);
asm("int $0x80");
}
int main(){
char *msg = "Hello, world!";
int len = strlen(msg);
printf("Len is %d\n*msg is %s\n", len, msg);
/* Print msg */
printmsg(msg, len);
/* Exit */
asm( "movl $1,%eax;"
"xorl %ebx,%ebx;"
"int $0x80"
);
}
Using Michael's extended assembly example:
#include <stdio.h>
#include <string.h>
void printmsg(char *string, int length){
asm( "int $0x80\n\t"
:
:"a"(4), "b"(1), "c"(string), "d"(length)
);
}
int main(){
char *string = "Hello, world!\n";
int variable = strlen(string);
/* Print msg */
printmsg(string, variable);
/* Exit */
asm( "movl $1,%eax;"
"xorl %ebx,%ebx;"
"int $0x80"
);
}
Related
Is there any way in GCC to represent inline __asm__ as char[] array? I want to have something like:
void my_func();
char my_code[] = {
__asm__("callq %0" :: "r" (my_func))
};
Later my_code will be used as run-time patch, i.e.
void another_function();
mprotect(another_function, getpagesize(), PROT_WRITE | PROT_READ | PROT_EXEC);
memcpy(another_function + offset, my_code, sizeof(my_code));
Any ideas?
You can just define a function, compile it, then get it's source machine code?
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
void my_func(void) {}
extern void my_code(void);
extern void my_code_end(void);
__attribute__((__used__)) static void _my_code(void) {
asm volatile(
".globl my_code\n"
"my_code:\n"
" callq *%0\n"
" nop\n"
" ret\n"
".globl my_code_end\n"
"my_code_end:\n"
:: "r" (my_func)
);
}
int main() {
size_t my_code_len = (uintptr_t)my_code_end - (uintptr_t)my_code;
const unsigned char *arr = (const char*)my_code;
printf("my_code[%zu]=", my_code_len);
for (size_t i = 0; i < my_code_len; ++i) {
printf("%02x", arr[i]);
}
printf("\n");
return 0;
}
Example output:
my_code[4]=ffd090c3
We can check it's ok from the assembly output:
$ objdump -D ./a.out
...
0000000000000727 <my_code>:
727: ff d0 callq *%rax
729: 90 nop
72a: c3 retq
...
What I do is
Get address of ExitProcess
Make space for opcode
Modify opcode in the space
Execute modified opcode by __asm__ ("jmp %%ecx"::"c"(opcode));
Here is my code:
#include <windows.h>
#include <stdio.h>
int main()
{
char addr[4];
*(int*)addr = GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
//push 0 == 0x6a 0x00
//call ExitProcess == 0xe8 0xd8 0x79 0xa2 0x75
char opcode[400] = {0x6a, 0x00, 0xe8,addr[0], addr[1],addr[2],addr[3]};
__asm__ ("jmp %%ecx" ::"c"(opcode));
//never be here
printf("never get here");
getchar();
return 0;
}
I expect program to exit normally, but the program terminates with a segmentation fault.
It seems that it jumps to somewhere, but not to the location I want it to jump.
How can I fix that?
Setting aside the odd thing you are trying to do...
Your problem is the opcode e8 is a relative jump. So you need to account for the address you are storing it at. Something like this maybe:
Update: Per taeyun, account for length of x.
#include <windows.h>
#include <stdio.h>
#pragma pack(1)
struct mfoo {
unsigned char x[3] = {0x6a, 0x00, 0xe8};
void *addr;
} foo;
int main()
{
unsigned char *a = (unsigned char *)GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
foo.addr = (void *)(a - sizeof(foo) - (unsigned char *)foo.x);
__asm__ ("jmp *%%ecx" ::"c"(&foo));
//never be here
printf("never get here");
getchar();
return 0;
}
I have a rather big project in Linux kernel (h.w).
part of needs to use the copy_to_user function,
for some reason, no matter what is the buffer size it will alyways return the buffer size (and not 0).
can you please help?
here is part of my code:
asmlinkage int sys_receive_mpi_message(int rank, char *message, ssize_t message_size)
{
int reader_rank =-10;
struct task_struct* p = NULL;
struct my_message_list* tmp;
struct list_head *pos, *q;
struct blabla* tmp1;
int bufSize = 0;
int res =0;
int i=0;
if ((rank < 0) || (rank > counter))
{
return -ESRCH;
}
list_for_each(pos, &(my_api_list->list))
{
tmp1 = list_entry(pos, struct blabla, list);
if (tmp1->pid == (current->pid))
{
reader_rank = tmp1->place;
p = tmp1->task_struct_p;
break;
}
}
if (reader_rank == -10)
{
return -ESRCH;
}
list_for_each_safe(pos,q, &(p->message_list->list))
{
tmp=list_entry(pos, struct my_message_list, list);
if (tmp->sender_rank == rank)
{
if (message_size > (tmp->meesage_size))
{
bufSize = tmp->meesage_size;
}
else
{
bufSize = message_size;
}
res = copy_to_user(message,tmp->message,bufSize);
if(res != 0)
{
return -EFAULT;
}
kfree(tmp->message);
list_del(pos);
kfree(tmp);
return (bufSize);
}
return -EFAULT;
}
return -EFAULT;
}
also, I have this struct :
struct my_message_list{
char* message;
int meesage_size;
int sender_rank;
struct list_head list;
};
Update- I foundout that the message I'm geting from the user points to 0 all the time!
does this tells me that the problem is in the wrapper function?
here is my rapper function(the relevent part):
#include <errno.h>
int receive_mpi_message(int rank, char* message, int message_size)
{
int res;
__asm__
(
"pushl %%eax;"
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%edx;"
"movl $245, %%eax;"
"movl %1, %%ebx;"
"int $0x80;"
"movl %%eax,%0;"
"popl %%edx;"
"popl %%ecx;"
"popl %%ebx;"
"popl %%eax;"
: "=m" (res)
:"m"(rank),"m"(message),"m"(message_size)
);
if (res >= (unsigned long)(-125))
{
errno = -res;
res = -1;
}
return (int) res;
}
What user-space interface do you use for communication? Regardless what user space interface you use (chardev, ioctl, ...), the signature of the function definitions where you hook in should have a __user attribute.
eg: fs.h
struct file_operations {
...
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
...
}
So the char *message variable should be char __user *message, just take a look at the user space interface you use.
Another thing could be that you are calling the method in the wrong place. As far is i know, the copy_*_user functions are only allowed on invocation from the user space. Please someone correct me if i am wrong.
Somehow the date you want to copy could not be copied, as for example, you cannot read the source or write to destination. It is explained at arch/x86/lib/usercopy_32.c:
/*
* Returns number of bytes that could not be copied.
* On success, this will be zero.
*/
I had a problem with my rapper function,
forogot to store data to all the registers:
int receive_mpi_message(int rank, char* message, int message_size)
{
int res;
__asm__
(
"pushl %%eax;"
"pushl %%ebx;"
"pushl %%ecx;"
"pushl %%edx;"
"movl $245, %%eax;"
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
"int $0x80;"
"movl %%eax,%0;"
"popl %%edx;"
"popl %%ecx;"
"popl %%ebx;"
"popl %%eax;"
: "=m" (res)
:"m"(rank),"m"(message),"m"(message_size)
);
if (res >= (unsigned long)(-125))
{
errno = -res;
res = -1;
}
return (int) res;
}
I am trying to write an inline assebly function which exchanges two values.( and i'm using extended ASM format)
This code works:
#include <stdio.h>
void Exchange(int *x, int *y)
{
printf("In Exchange function: Before exchange x is: %d\n",*x);
printf("In Exchange function: Before exchange y is: %d\n",*y);
asm("xchg %%eax,%%edx\n\t" \
:"+a"(*x),"+d"(*y));
printf("In Exchange function: After exchange x is: %d\n",*x);
printf("In Exchange function: After exchange y is: %d\n",*y);
}
int main()
{
int x=20;
int y=30;
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);
return 0;
}
but when i try to wirte it in full assembly like below i get segmentation fault (core dumped) error.
void Exchange(int *x, int *y)
{
asm("subl $8,%%esp\n\t" \
"movl %%eax,4(%%esp)\n\t" \
"movl %%edx,(%%esp)\n\t" \
"call printf\n\t" \
"addl $8,%%esp\n\t" \
"xchg %%eax,%%edx\n\t" \
"subl $8,%%esp\n\t" \
"movl %%eax,4(%%esp)\n\t" \
"movl %%edx,(%%esp)\n\t" \
"call printf\n\t" \
"addl $8,%%esp\n\t" \
:"+a"(*x),"+d"(*y));
}
int main()
{
int x=20;
int y=30;
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);
return 0;
}
Aren't we allowed to use printf function in the assembly section?
Your asm code calls printf with two integer arguments -- no format string. So it tries to dereference the first integer as a pointer to a format string and crashes.
Also, calling printf will clobber the values in %eax and %edx, as they are not preserved across calls in the standard x86 calling conventions.
I've built a short program written on C and inline assembly on my linux x86_64. It is supposed to write a string to stdout. I found it in an article on the internet:
int write_call( int fd, const char * str, int len ){
long __res;
__asm__ volatile ( "int $0x80":
"=a" (__res):"0"(__NR_write),"b"((long)(fd)),"c"((long)(str)),"d"((long)(len)) );
return (int) __res;
}
void do_write( void ){
char * str = "Paragon output string.\n";
int len = strlen( str ), n;
printf( "string for write length = %d\n", len );
n = write_call( 1, str, len );
printf( "write return : %d\n", n );
}
int main( int argc, char * argv[] ){
do_write();
return EXIT_SUCCESS;
}
But as I run it, it works incorrectly, making output
"write return : -14"
If I build and run it on 32-bit linux it does what is expected.
After some research I fount out that instruction "int $0x80" is a x86 instruction and truncates arguments in registers if called on x86_64.
But I couldn't find a proper substitution of "int $0x80" for x86_64 architecture. I have zero experience in assembly.
What should I put instead of "int $0x80" to receive expected result?
For amd64, you need to use "syscall" - and use different registers - instead of "int 0x80":
http://cs.lmu.edu/~ray/notes/linuxsyscalls/
http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64
http://crypto.stanford.edu/~blynn/rop/
Here's a good example:
How to invoke a system call via sysenter in inline assembly (x86/amd64 linux)?
#include <unistd.h>
int main(void)
{
const char hello[] = "Hello World!\n";
const size_t hello_size = sizeof(hello);
ssize_t ret;
asm volatile
(
"movl $1, %%eax\n\t"
"movl $1, %%edi\n\t"
"movq %1, %%rsi\n\t"
"movl %2, %%edx\n\t"
"syscall"
: "=a"(ret)
: "g"(hello), "g"(hello_size)
: "%rdi", "%rsi", "%rdx", "%rcx", "%r11"
);
return 0;