Forum

> > Off Topic > What does this piece of code do?
Forums overviewOff Topic overviewLog in to reply

English What does this piece of code do?

10 replies
To the start Previous 1 Next To the start

old What does this piece of code do?

Lee
Moderator Off Offline

Quote
1
2
3
4
5
6
7
8
#include <stdio.h>

void disp(int n){printf("%d ", n&(0xffff));}

int main(){
	((int(*)())"\x66\x31\xc0\x8b\x5c\x24\x04\x66\x40\x50\xff\xd3\x58\x66\x3d\xe8\x03\x75\xf4\xc3")(&disp);
	return 0;
}

Note: only works on x86 gcc/tcc/cc compilers.

old Re: What does this piece of code do?

Psytechnic
User Off Offline

Quote
Does it display a word???

The code looks like it prints out the letters you've defined and something else. You've overloaded it with set values that print out the character version followed by a modification I don't recognised ("n&(0xffff));"). It'll be interesting to find out what it actually does.

This is completely at first glance.

old Re: What does this piece of code do?

Lee
Moderator Off Offline

Quote
Yeah, it's C, you can actually compile it on GCC or run it on codepad.org.

@Psytechnic: n is an integer, for which the largest value can be expressed as 0xffffffff (actually +1, 32 bit), hence n&(0xffff) zeros all of the bytes above the 16th bit. This effectively "casts" an integer into a short integer via only the specified bytes (I think (short)n would work just as well here, but since I'm passing it in as a parameter, the printf function will still look for an 32 bit integer so on certain compilers that do not reallocate on downcast, this will return the incorrect result)

Hints:
* int(*)() is the signature for a function

* The hexadecimal representation of 1000 is 0x03e8, which in contiguous memory looks like

0x03,0xe8 in big endian
0xe8,0x03 in little endian

Edit: @EngiN33R, spot on mate, how did you know?
edited 1×, last 19.02.11 07:49:12 pm

old Re: What does this piece of code do?

Psytechnic
User Off Offline

Quote
Well, the code prints out every number between 1 and 1000... but I can tell you've used an unusual method for a reason. I just don't know what that reason is. There are other (IMO: visually simpler) ways to accomplish the same result, but what is it about this particular method that makes it useful?

old Re: What does this piece of code do?

DannyDeth
User Off Offline

Quote
Well, this seems considerably more complex than anything I have ever coded. I only have seen this a couple times actually, one of them was my first class with Prof. Hughes, but toning down some of the brackets and adding some tabs I kinda see something.

It's actually just plain messed up anyway. But I see basically what it is doing, although I cannot be sure, the mass of \ things leaves me flabbergasted, I don't exactly use them everyday      I don't see this as an easily understood task.

Ok, so, I will try now ( bare in mind I'm probably going to be wrong ) :

The large amount of \ thingies are actually acting similar to a function and producing the numbers which are then passed on to disp to be printed to the screen.

To be honest this is just a guess after looking through the code a couple times. Really it seems a bit over my head

EDIT: infact I have forgotten the name of the \ things, damn. I'm getting stupid
edited 1×, last 21.02.11 02:41:51 pm

old Re: What does this piece of code do?

Lee
Moderator Off Offline

Quote
@Psy and Danny:

Haha, it's more or less something that you should never ever do in production, but is still very interesting

1
void disp(int n){printf("%d ", n&(0xffff));}

This creates a function disp that when given an integer, issues a call to printf to print the first 16 bits (2bytes) of that integer.

Now a backslash (\) in a string denotes that the following sequence of characters are to be considered as a special escape sequence. '\x0' is equivalent to the ascii character whose character-code is 0, and '\x20' is equivalent to the ascii character whose code is 32 (x20 is in hexadecimal). But let's break from tradition here. Because is character is just a byte in memory, we can also consider a string to be a byte stream (array of byte) containing some arbitrary data.

Here's the interesting part:

let's assume that you have some arbitrary function

1
void random_func(){}

We can actually recast this function to do something else entirely:

1
(int(*)()) &random_func; // Casts random_func to a function that returns int

so that when you call int i = ((int(*)()) &random_func)(), the function will actually return an integer which is assigned to i.

This is what int(*)() means. It's a function signature that denotes the return type of some function.

While people don't usually cast strings into functions, it's possible.

1
(int(*)())"Hi Mom!" // <- this is a function. You can call it.

// Note: "Hi Mom!" has the type (const char*), which is a pointer to a part of the memory that is created OFF the heap (not important right now, I'll talk about this later) and is actually an integer type.

Of course, when you do actually call that function, you will get an error because the computer doesn't know what to do when it tries to compute "Hi Mom!".


So what can be used to call a function?

Well, since strings can be converted into functions, why can't we convert functions into strings?

1
(char*) &random_func; // This is what the string of a func looks like

I won't bore you with the details but upon further investigation, a function is made up of a bunch of illegible characters that form the machine code of the function (surprise).

So if we simply type machine code into a string and then cast it into a function, it'll compile and run that machine code right?

Well, not quite. Take the following instance for example:

1
2
((int(*)())"\xc3... valid machine code ...")() // This will run and return an arbitrary number
((int(*)())(char*)"\xc3... valid machine code ...")() // This will crash and cause a segmentation fault

If the first compiled, and then we casted that string to the same string and then into a function, why would that fail?

The simple answer is that only (const char*) can be executed.

More >


So onto the rest of the code

"\x66\x31\xc0\x8b\x5c\x24\x04\x66\x40\x50\xff\xd3\x58\x66\x3d\xe8\x03\x75\xf4\xc3"

This is machine code that can be roughly translated into the following assembly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int FORLOOP(int addr){ // addr is four bytes below the top of the stack (which is at the bottom) -> 4(%exp) or [%esp + 4]
// From now on, (;) starts a comment

    xor %ax, %ax ; zeros ax
    mov 4(%esp), %ebx ; saves esp+4 (addr of addr or the function) to ebx

    body: ; this isn't actually in the code
    inc %ax ; add one to ax (this will print from 1 to 1000 instead of 0-999)
    push %eax ; pushes eax onto the stack so that it'll be passed into the function call next line
    call *%ebx ; calls *addr, which should point to a function such as &disp
    pop %eax ; pop eax off the stack assuming disp did not use eax
    cmp $1000, %ax ; compare
    jne body ; if ax is not 1000, goto body

    ret
}

So by passing in the address of the disp function, this calls disp 1000 times, each time passing in the %ax registor, which is used as the counter of the for loop.

old Re: What does this piece of code do?

Psytechnic
User Off Offline

Quote
Nice...

Now let me just go throw up from that massive influx of information to the brain...

It's amazing how such a small piece of code can do so much by simply recursing itself over and over. Excuse me, seriously, I'm nauseous...

old Re: What does this piece of code do?

DannyDeth
User Off Offline

Quote
Ahah, nice Lee. I found this on Google, your code seems to me like the most complex that was posted there

But yeah, I understood that disp was cutting short the integer to a short int via n&(0xFFFF), the rest seemed like a chinglish product manual to me, you know, you can read it and it part makes sense, but then you reach the middle and realise you have actually put the wing nut in the wrong hole

It's interesting to see the different uses of C and all of it's low-level aspects, I especially like how you can use machine-code straight inside your C, it opens up new windows of opportunity.

But if I hear you right, you can actually take your function and take/execute it's machine code via:
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

void func(int i){
	printf("%d\n",i);
}

int main(void){
	(const char*) fun = ((char*) func())
	((int(*)())""+fun+"")(1);
}
I highly doubt that would work I am pretty new to this whole executing machine code from C thing
To the start Previous 1 Next To the start
Log in to replyOff Topic overviewForums overview