Сидел чета, тупил-тупил, и вдруг стало интересно, а можно ли в Си просто взять и запустить какой-то байт код?
Ассемблировал с помощью NASM'а очень сложную программу на ассемблере:
jmp $
Что в переводе значит "перейти на текущую команду".
NASM крут тем, что может выдавать "flat-form binary", короче не экзешник в формате для какой-либо операционной системы, а просто чистый байт код который непосредственно выполняется процом.
Присвоил пойнтеру на функцию типа void funcname(void) адрес массива с байткодом. Вызвал функцию на выполнение.
#include
#include
void myFunc(void);
int
main(int argc, char **argv)
{
/*
* Declare variable 'pfunc', which holds an address
* of a function that takes no parameters and returns
* no value.
*/
void (*pfunc) (void);
/*
* Byte code for instruction
* jmp $ (jump to current command)
* as assembeled by NASM.
*/
unsigned char bytecode[] = { 0xeb, 0xfe };
printf("main() address: 0x%x\n", & main);
pfunc = & myFunc;
printf("pfunc = 0x%x\n", pfunc);
(*pfunc)();
/* pfunc = address of first byte in array bytecode */
pfunc = (void (*) (void)) bytecode;
printf("pfunc = 0x%x\n", pfunc);
(*pfunc)();
return 0;
}
void
myFunc(void)
{
printf("myFunc executed!\n");
}
Результаты выполнения:
Win2000, Open Watcom C/C++:
C:\>test
main() address: 0x401010
pfunc = 0x401066
myFunc executed!
pfunc = 0x12fe8c
^C
C:\>
Win2000, Visual C++ 6.0:
C:\>test
main() address: 0x401000
pfunc = 0x40105b
myFunc executed!
pfunc = 0x12ff7c
^C
C:\>
Win2000, lcc-win32:
C:\>test
main() address: 0x4012d4
pfunc = 0x40133b
myFunc executed!
pfunc = 0x12ff6a
^C
C:\>
OpenBSD, gcc:
root@slowpoke:1:~$ ./test
main() address: 0x1c0005d0
pfunc = 0x1c00066b
myFunc executed!
pfunc = 0xcfbceb14
Segmentation fault (core dumped)
root@slowpoke:1:~$
То есть какбе получается что в винде секция (или как там это называется) данных по умолчанию executab'ельна.
Жаль нету линукса или хотя бы другой БСД позырить как там.
Олсо, туториал по пойнтерам на функции.