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
Related
I am trying to implement getrusage function into my client server program using sockets and all of this is running on FreeBSD. I want to print out processor time usage and memory usage.
I have tried to implement the following code but I am getting output Illegal instrucion (Core dumped)
int getrusage(int who, struct rusage *usage){
int errorcode;
__asm__(
"syscall"
: "=a" (errorcode)
: "a" (117), "D" (who), "S" (usage) //const Sysgetrusage : scno = 117
: "memory"
);
if (errorcode<0) {
printf("error");
}
return 1;
}
UPDATE: I have tried to run this but I get zero values or some random number value or negative number values. Any ideas what am I missing?
int getrusage(int who, struct rusage *usage){
int errorcode;
__asm__("push $0;"
"push %2;"
"push %1;"
"movl $117, %%eax;"
"int $0x80;"
:"=r"(errorcode)
:"D"(who),"S"(usage)
:"%eax"
);
if (errorcode<0) {
printf("error");
}
return 1;
}
I would like to use system call write more likely, but it is giving me a compilation warning: passing arg 1 of 'strlen' makes pointer from integer without a cast
EDIT: (this is working code now, regarding to comment)
struct rusage usage;
getrusage(RUSAGE_SELF,&usage);
char tmp[300];
write(i, "Memory: ", 7);
sprintf (tmp, "%ld", usage.ru_maxrss);
write(i, tmp, strlen(tmp));
write(i, "Time: ", 5);
sprintf (tmp, "%lds", usage.ru_utime.tv_sec);
write(i, tmp, strlen(tmp));
sprintf (tmp, "%ldms", usage.ru_utime.tv_usec);
write(i, tmp, strlen(tmp));
Any ideas what is wrong?
The reason you are getting an illegal instruction error is because the SYSCALL instruction is only available on 64-bit FreeBSD running a 64-bit program. This is a serious issue since one of your comments suggests that your code is running on 32-bit FreeBSD.
Under normal circumstances you don't need to write your own getrusage since it is part of the C library (libc) on that platform. It appears you have been tasked to do it with inline assembly.
64-bit FreeBSD and SYSCALL Instruction
There is a bit of a bug in your 64-bit code since SYSCALL destroys the contents of RCX and R11. Your code may work but may fail in the future especially as the program expands and you enable optimizations. The following change adds those 2 registers to the clobber list:
int errorcode;
__asm__(
"syscall"
: "=a" (errorcode)
: "a" (117), "D" (who), "S" (usage) //const Sysgetrusage : scno = 117
: "memory", "rcx", "r11"
);
Using the memory clobber can lead to generation of inefficient code so I use it only if necessary. As you become more of an expert the need for memory clobber can be eliminated. I would have used a function like the following if I wasn't allowed to use the C library version of getrusage:
int getrusage(int who, struct rusage *usage){
int errorcode;
__asm__(
"syscall"
: "=a"(errorcode), "=m"(*usage)
: "0"(117), "D"(who), "S"(usage)
: "rcx", "r11"
);
if (errorcode<0) {
printf("error");
}
return errorcode;
}
This uses a memory operand as an output constraint and drops the memory clobber. Since the compiler knows how large a rusage structure and is =m says the output constraint modifies that memory we don't need need the memory clobber.
32-bit FreeBSD System Calls via Int 0x80
As mention in the comments and your updated code, to make a system call in 32-bit code in FreeBSD you have to use int 0x80. This is described in the FreeBSD System Calls Convention. Parameters are pushed on the stack right to left and you must allocate 4 bytes on the stack by pushing any 4 byte value onto the stack after you push the last parameter.
Your edited code has a few bugs. First you push the extra 4 bytes before the rest of the arguments. You need to push it after. You need to adjust the stack after int 0x80 to effectively reclaim the stack space used by the arguments passed. You pushed three 4-byte values on the stack, so you need to add 12 to ESP after int 0x80.
You also need a memory clobber because the compiler doesn't know you have actually modified memory at all. This is because the way you have done your constraints the data in the variable usage gets modified but the compiler doesn't know what.
The return value of the int 0x80 will be in EAX but you use the constraint =r. It should have been =a since the return value will be returned in EAX. Since using =a tells the compiler EAX is clobbered you don't need to list it as a clobber anymore.
The modified code could have looked like:
int getrusage(int who, struct rusage *usage){
int errorcode;
__asm__("push %2;"
"push %1;"
"push $0;"
"movl $117, %%eax;"
"int $0x80;"
"add $12, %%esp"
:"=a"(errorcode)
:"D"(who),"S"(usage)
:"memory"
);
if (errorcode<0) {
printf("error");
}
return errorcode;
}
Another way one could have written this with more advanced techniques is:
int getrusage(int who, struct rusage *usage){
int errorcode;
__asm__("push %[usage]\n\t"
"push %[who]\n\t"
"push %%eax\n\t"
"int $0x80\n\t"
"add $12, %%esp"
:"=a"(errorcode), "=m"(*usage)
:"0"(117), [who]"ri"(who), [usage]"r"(usage)
:"cc" /* Don't need this with x86 inline asm but use for clarity */
);
if (errorcode<0) {
printf("error");
}
return errorcode;
}
This uses a label (usage and who) to identify each parameter rather than using numerical positions like %3, %4 etc. This makes the inline assembly easier to follow. Since any 4-byte value can be pushed onto the stack just before int 0x80 we can save a few bytes by simply pushing the contents of any register. In this case I used %%eax. This uses =m constraint like I did in the 64-bit example.
More information on extended inline assembler can be found in the GCC documentation.
Using i686-elf-gcc and i686-elf-ld to compile and link.
/tmp/ccyjfCee.s:25: Error: invalid instruction suffix for 'mov'
makefile:21: recipe for target 'Release/boot.o' failed
When I tried to modify movw %0, %%dx to movw $0x1, %%dx. It compiled and linked successfully. So I wonder why there is something wrong with the line. In light of .code16, the offset address of pStr should be 16bit, which fits into dx register well. What's wrong with it?
__asm__(".code16\n");
void printString(const char* pStr) {
__asm__ __volatile__ ("movb $0x09, %%ah\n\t"
"movw %0, %%dx\n\t"
"int $0x21"
:
:"r"(pStr)
:"%ah", "%dx");
}
void _start() {
printString("Hello, World");
}
Technically you can use the .code16gcc directive to generate 16 bit code and the %w0 substitution to force word sized register.
Note that the above will only let you create a program that will run in 16 bit real mode under DOS (after some postprocessing to get it to the proper format). If that's not what you want, you will need to use the appropriate OS system calls instead of int 0x21 and not write 16 bit code.
This function "strcpy" aims to copy the content of src to dest, and it works out just fine: display two lines of "Hello_src".
#include <stdio.h>
static inline char * strcpy(char * dest,const char *src)
{
int d0, d1, d2;
__asm__ __volatile__("1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0"(src),"1"(dest)
: "memory");
return dest;
}
int main(void) {
char src_main[] = "Hello_src";
char dest_main[] = "Hello_des";
strcpy(dest_main, src_main);
puts(src_main);
puts(dest_main);
return 0;
}
I tried to change the line : "0"(src),"1"(dest) to : "S"(src),"D"(dest), the error occurred: ‘asm’ operand has impossible constraints. I just cannot understand. I thought that "0"/"1" here specified the same constraint as the 0th/1th output variable. the constraint of 0th output is =&S, te constraint of 1th output is =&D. If I change 0-->S, 1-->D, there shouldn't be any wrong. What's the matter with it?
Does "clobbered registers" or the earlyclobber operand(&) have any use? I try to remove "&" or "memory", the result of either circumstance is the same as the original one: output two lines of "Hello_src" strings. So why should I use the "clobbered" things?
The earlyclobber & means that the particular output is written before the inputs are consumed. As such, the compiler may not allocate any input to the same register. Apparently using the 0/1 style overrides that behavior.
Of course the clobber list also has important use. The compiler does not parse your assembly code. It needs the clobber list to figure out which registers your code will modify. You'd better not lie, or subtle bugs may creep in. If you want to see its effect, try to trick the compiler into using a register around your asm block:
extern int foo();
int bar()
{
int x = foo();
asm("nop" ::: "eax");
return x;
}
Relevant part of the generated assembly code:
call foo
movl %eax, %edx
nop
movl %edx, %eax
Notice how the compiler had to save the return value from foo into edx because it believed that eax will be modified. Normally it would just leave it in eax, since that's where it will be needed later. Here you can imagine what would happen if your asm code did modify eax without telling the compiler: the return value would be overwritten.
I'm trying to use a small amount of AT&T style inline assembly in C and GCC by reading an article on CodeProject here. The main reason I wish to do this is to find the old value of the EIP register to be able to have a reliable address of instructions in my code. I have written a simple example program to demonstrate my understanding of this concept thus far :
#include <stdio.h>
#include <stdlib.h>
int mainReturnAddress = 0;
int main()
{
asm volatile (
"popl %%eax;"
"pushl %%eax;"
"movl %%eax, %0;"
: "=r" ( mainReturnAddress )
);
printf( "Address : %d\n", mainReturnAddress );
return 0;
}
The purpose of this particular example is to pop 4 bytes from the top of the stack representing the 32 bit return address saved from the EIP register, and then to push it back on the stack. Afterwards, I store it in the global mainReturnAddress variable. Finally, I print the value stored in mainReturnAddress.
The output from I recieve from this code 4200560.
Does this code achieve the purpose aforementioned, and is this is cross processor on the Windows platform 32-bit?
In GCC, you should use __builtin_return_address rather then trying to use inline assembly.
I am writing Inline assembly for the first time and I don't know why I'm getting a Seg fault when I try to run it.
#include <stdio.h>
int very_fast_function(int i){
asm volatile("movl %%eax,%%ebx;"
"sall $6,%%ebx;"
"addl $1,%%ebx;"
"cmpl $1024,%%ebx;"
"jle Return;"
"addl $1,%%eax;"
"jmp End;"
"Return: movl $0,%%eax;"
"End: ret;": "=eax" (i) : "eax" (i) : "eax", "ebx" );
return i;
/*if ( (i*64 +1) > 1024) return ++i;
else return 0;*/
}
int main(int argc, char *argv[])
{
int i;
i=40;
printf("The function value of i is %d\n", very_fast_function(i));
return 0;
}
Like I said this is my first time so if it's super obvious I apologize.
You shall not use ret directly. Reason: there're initialization like push the stack or save the frame pointer when entering each function, also there're corresponding finalization. You just leave the stack not restored if use ret directly.
Just remove ret and there shall not be segmentation fault.
However I suppose the result is not as expected. The reason is your input/output constrains are not as expected. Please notice "=eax" (i) you write does not specify to use %%eax as the output of i, while it means to apply constraint e a and x on output variable i.
For your purpose you could simply use r to specify a register. See this edited code which I've just tested:
asm volatile("movl %1,%%ebx;"
"sall $6,%%ebx;"
"addl $1,%%ebx;"
"cmpl $1024,%%ebx;"
"jle Return;"
"addl $1,%0;"
"jmp End;"
"Return: movl $0,%0;"
"End: ;": "=r" (i) : "r" (i) : "ebx" );
Here To use %%eax explicitly, use "=a" instead of "=r".
For further information, please read this http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
ret should not be used in inline assembly blocks - the function you're in needs some cleanup beyond what a simple ret will handle.
Remember, inline assembly is inserted directly into the function it's embedded in. It's not a function unto itself.