Какая функция выполняется в коде? - PullRequest
0 голосов
/ 28 февраля 2020

Я нашел следующий код онлайн

void main(void)
{
  ((void(*)()) "\xeb\x11\x59\x31\xc0\x31\xdb\x31\xd2\xb0\x04\xb3\x01\xb2\x36\xcd\x80\xeb\xf6\xe8\xea\xff\xff\xff\x48\x6f\x6c\x62\x65\x72\x74\x6f\x6e\x20\x3c\x33\x20\x40\x6b\x61\x6c\x6f\x75\x30\x30\x30\x20\x2b\x20\x40\x67\x61\x6e\x64\x69\x62\x61\x72\x20\x2b\x20\x40\x53\x74\x65\x70\x68\x61\x6e\x47\x61\x6e\x64\x69\x20\x3a\x29\x0a")();
}

При компиляции и запуске этого кода постоянно печатается следующее:

Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)
Holberton <3 @kalou000 + @gandibar + @StephanGandi :)

Подскажите, пожалуйста, как это работает?

Я скомпилировал это с флагом -m32. Глядя на вывод strace, он постоянно вызывает системный вызов write

write(1, "Holberton <3 @kalou000 + @gandib"..., 54Holberton <3 @kalou000 + @gandibar + @StephanGandi :)

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

в c вы можете делать невероятные вещи. это один из них.

вы видите простой буфер, но это не так. это машинный код, представленный в шестнадцатеричной строке.

этот буфер приводится к функции void, а затем вызывается.

"\xeb\x11\x59\x31\xc0..." - это тело функции в машинном коде, и когда он приводится к (void(*)()) она стала функцией в коде и затем вызывается ();

в c, которую вы можете привести к любому. когда компилятор видит ();, собирает инструкцию перехода к первому байту, а затем позволяет процессору выполнять остальные.

- вот как это работает.

0 голосов
/ 28 февраля 2020

Если вы хотите стать мастером таких программ, вы можете проверить io ccc соревнование .

В коде, который вы вставили, вы конвертируете указатель из объекта в указатель на функцию и вы переходите с выполнения по адресу объекта. В этом месте находятся данные из строкового объекта. Вы вставили в эту строку данные, которые фактически представляют код.

Чтобы увидеть, что этот код представляет, я вставил его в дизассемблер, см. здесь :

Disassembly
Raw Hex (zero bytes in bold):

EB115931C031DB31D2B004B301B236CD80EBF6E8EAFFFFFF486F6C626572746F6E203C3320406B616C6F75303030202B204067616E6469626172202B20405374657068616E47616E6469203A290A   

String Literal:

"\xEB\x11\x59\x31\xC0\x31\xDB\x31\xD2\xB0\x04\xB3\x01\xB2\x36\xCD\x80\xEB\xF6\xE8\xEA\xFF\xFF\xFF\x48\x6F\x6C\x62\x65\x72\x74\x6F\x6E\x20\x3C\x33\x20\x40\x6B\x61\x6C\x6F\x75\x30\x30\x30\x20\x2B\x20\x40\x67\x61\x6E\x64\x69\x62\x61\x72\x20\x2B\x20\x40\x53\x74\x65\x70\x68\x61\x6E\x47\x61\x6E\x64\x69\x20\x3A\x29\x0A"

Array Literal:

{ 0xEB, 0x11, 0x59, 0x31, 0xC0, 0x31, 0xDB, 0x31, 0xD2, 0xB0, 0x04, 0xB3, 0x01, 0xB2, 0x36, 0xCD, 0x80, 0xEB, 0xF6, 0xE8, 0xEA, 0xFF, 0xFF, 0xFF, 0x48, 0x6F, 0x6C, 0x62, 0x65, 0x72, 0x74, 0x6F, 0x6E, 0x20, 0x3C, 0x33, 0x20, 0x40, 0x6B, 0x61, 0x6C, 0x6F, 0x75, 0x30, 0x30, 0x30, 0x20, 0x2B, 0x20, 0x40, 0x67, 0x61, 0x6E, 0x64, 0x69, 0x62, 0x61, 0x72, 0x20, 0x2B, 0x20, 0x40, 0x53, 0x74, 0x65, 0x70, 0x68, 0x61, 0x6E, 0x47, 0x61, 0x6E, 0x64, 0x69, 0x20, 0x3A, 0x29, 0x0A }

Disassembly:
0:  eb 11                   jmp    0x13
2:  59                      pop    ecx
3:  31 c0                   xor    eax,eax
5:  31 db                   xor    ebx,ebx
7:  31 d2                   xor    edx,edx
9:  b0 04                   mov    al,0x4
b:  b3 01                   mov    bl,0x1
d:  b2 36                   mov    dl,0x36
f:  cd 80                   int    0x80
11: eb f6                   jmp    0x9
13: e8 ea ff ff ff          call   0x2
18: 48                      dec    eax
19: 6f                      outs   dx,DWORD PTR ds:[esi]
1a: 6c                      ins    BYTE PTR es:[edi],dx
1b: 62 65 72                bound  esp,QWORD PTR [ebp+0x72]
1e: 74 6f                   je     0x8f
20: 6e                      outs   dx,BYTE PTR ds:[esi]
21: 20 3c 33                and    BYTE PTR [ebx+esi*1],bh
24: 20 40 6b                and    BYTE PTR [eax+0x6b],al
27: 61                      popa
28: 6c                      ins    BYTE PTR es:[edi],dx
29: 6f                      outs   dx,DWORD PTR ds:[esi]
2a: 75 30                   jne    0x5c
2c: 30 30                   xor    BYTE PTR [eax],dh
2e: 20 2b                   and    BYTE PTR [ebx],ch
30: 20 40 67                and    BYTE PTR [eax+0x67],al
33: 61                      popa
34: 6e                      outs   dx,BYTE PTR ds:[esi]
35: 64 69 62 61 72 20 2b    imul   esp,DWORD PTR fs:[edx+0x61],0x202b2072
3c: 20
3d: 40                      inc    eax
3e: 53                      push   ebx
3f: 74 65                   je     0xa6
41: 70 68                   jo     0xab
43: 61                      popa
44: 6e                      outs   dx,BYTE PTR ds:[esi]
45: 47                      inc    edi
46: 61                      popa
47: 6e                      outs   dx,BYTE PTR ds:[esi]
48: 64                      fs
49: 69                      .byte 0x69
4a: 20 3a                   and    BYTE PTR [edx],bh
4c: 29 0a                   sub    DWORD PTR [edx],ecx

Это код не является переносимым.

C язык, позволяющий использовать этот вид конструкций, является примером homoiconi c language - языка, на котором действует парадигма «код - это данные, а данные - это код» (нет различия между кодом и данными). Если вы программируете на lisp-подобных языках, такой тип программирования очень распространен. Однако в C он используется редко.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...