Получение 128-битного ключа из шеллкода

Я пытаюсь вытащить 128-битный ключ из шеллкода. Я скомпилировал шелл-код как код C внутри массива, похожего на

#include <stdio.h>
#include <stdlib.h>
/*shellcode.c*/
char code[] = "\x31\xC0\x50\x68\x75\x70\x25\x75\x68\x23\x78\x27\x78\x68\x25\x74\x72\x20\x68\x79\x24\x73\x77\x68\x71\x72\x77\x76\x68\x20\x25\x22\x70\x68\x23\x78\x75\x27\x68\x75\x20\x23\x75\x68\x76\x72\x79\x79\x68\x20\x70\x72\x73\x68\x71\x71\x24\x25\x68\x79\x27\x76\x77\x68\x24\x77\x71\x72\x68\x27\x79\x70\x70\x68\x74\x24\x24\x75\x68\x79\x73\x23\x23\x68\x74\x22\x75\x79\x68\x23\x74\x70\x27\x68\x20\x74\x24\x79\x68\x74\x77\x24\x78\x68\x25\x27\x70\x75\x68\x74\x77\x74\x78\x68\x23\x23\x71\x76\x68\x77\x70\x73\x71\x68\x27\x20\x77\x24\x68\x22\x72\x78\x75\x68\x25\x72\x79\x77\x68\x23\x75\x79\x76\x68\x72\x71\x72\x24\x68\x71\x23\x23\x79\x68\x79\x23\x79\x70\x68\x20\x20\x76\x77\x54\x5E\x8B\xFE\x8B\xD7\xFC\xB9\x80\x00\x00\x00\xBB\x41\x00\x00\x00\x31\xC0\x50\xAC\x33\xC3\xAA\xE2\xFA\x54\x5E\xCC";
int main(int argc, char **argv)
{
int (*func)();
func = (int (*)()) code;
(int)(*func)();
}

когда я скомпилировал его с помощью GCC под Linux. После дизассемблирования с помощью GDB, так как шеллкод находится внутри массива кода;

(gdb) disas &code
Dump of assembler code for function code:
   0x0000000000600840 <+0>: xor    %eax,%eax
   0x0000000000600842 <+2>: push   %rax
   0x0000000000600843 <+3>: pushq  $0x75257075
   0x0000000000600848 <+8>: pushq  $0x78277823
   0x000000000060084d <+13>:    pushq  $0x20727425
   0x0000000000600852 <+18>:    pushq  $0x77732479
   0x0000000000600857 <+23>:    pushq  $0x76777271
   0x000000000060085c <+28>:    pushq  $0x70222520
   0x0000000000600861 <+33>:    pushq  $0x27757823
   0x0000000000600866 <+38>:    pushq  $0x75232075
   0x000000000060086b <+43>:    pushq  $0x79797276
   0x0000000000600870 <+48>:    pushq  $0x73727020
   0x0000000000600875 <+53>:    pushq  $0x25247171
   0x000000000060087a <+58>:    pushq  $0x77762779
   0x000000000060087f <+63>:    pushq  $0x72717724
   0x0000000000600884 <+68>:    pushq  $0x70707927
   0x0000000000600889 <+73>:    pushq  $0x75242474
   0x000000000060088e <+78>:    pushq  $0x23237379
   0x0000000000600893 <+83>:    pushq  $0x79752274
   0x0000000000600898 <+88>:    pushq  $0x27707423
   0x000000000060089d <+93>:    pushq  $0x79247420
   0x00000000006008a2 <+98>:    pushq  $0x78247774
   0x00000000006008a7 <+103>:   pushq  $0x75702725
   0x00000000006008ac <+108>:   pushq  $0x78747774
   0x00000000006008b1 <+113>:   pushq  $0x76712323
   0x00000000006008b6 <+118>:   pushq  $0x71737077
   0x00000000006008bb <+123>:   pushq  $0x24772027
   0x00000000006008c0 <+128>:   pushq  $0x75787222
   0x00000000006008c5 <+133>:   pushq  $0x77797225
   0x00000000006008ca <+138>:   pushq  $0x76797523
   0x00000000006008cf <+143>:   pushq  $0x24727172
   0x00000000006008d4 <+148>:   pushq  $0x79232371
   0x00000000006008d9 <+153>:   pushq  $0x70792379
   0x00000000006008de <+158>:   pushq  $0x77762020
   0x00000000006008e3 <+163>:   push   %rsp
   0x00000000006008e4 <+164>:   pop    %rsi
   0x00000000006008e5 <+165>:   mov    %esi,%edi
   0x00000000006008e7 <+167>:   mov    %edi,%edx
   0x00000000006008e9 <+169>:   cld    
   0x00000000006008ea <+170>:   mov    $0x80,%ecx
   0x00000000006008ef <+175>:   mov    $0x41,%ebx
   0x00000000006008f4 <+180>:   xor    %eax,%eax
   0x00000000006008f6 <+182>:   push   %rax
   0x00000000006008f7 <+183>:   lods   %ds:(%rsi),%al
   0x00000000006008f8 <+184>:   xor    %ebx,%eax
   0x00000000006008fa <+186>:   stos   %al,%es:(%rdi)
   0x00000000006008fb <+187>:   loop   0x6008f7 <code+183>
   0x00000000006008fd <+189>:   push   %rsp
   0x00000000006008fe <+190>:   pop    %rsi
   0x00000000006008ff <+191>:   int3   
   0x0000000000600900 <+192>:   add    %al,(%rax)
End of assembler dump.

Глядя на разборку, 128-битный ключ будет рассчитан после инструкций цикла на 6008fb. Мне не очень удобно работать с GDB. Как я могу получить 128-битный ключ из этого шеллкода? Я подозреваю, что мне нужно поместить указатель сразу после цикла и просмотреть содержимое? Но я не знаю, как это сделать. Заранее большое спасибо ...


person user1098896    schedule 15.01.2013    source источник


Ответы (1)


Если вы сможете успешно запустить этот код, он остановится на инструкции int3 в конце. В этот момент у вас будет расшифрованная строка в памяти, начинающаяся с rsp+8 (что совпадает с rsi+8). Вы можете распечатать его, например, с gdb по x/s $rsp+8. +8 происходит от push %rax в 0x6008f6.

Обратите внимание, что этот код кажется ошибочно перенесенным 32-битным кодом. Все инструкции pushq будут хранить непосредственную константу, указанную в инструкции, за которой следуют 4 нулевых байта. Расшифровка этого приведет к тому, что каждые 4 буквы будут отображаться как AAAA (и будет получена только половина ключа). mov %esi,%edi в 0x6008e5 обнуляет старшие биты rdi, поэтому код будет работать только в том случае, если стек находится в первых 4 ГБ адресного пространства (чего обычно нет в 64-битной системе).

Кроме того, код предполагает, что он находится в стеке, но ваша оболочка C помещает его в раздел данных. В любом случае вам также понадобятся права на выполнение.

В качестве альтернативы, поскольку этот код не делает ничего, кроме операции XOR со значениями с помощью 0x41, вы можете легко сделать это вручную, помня, что x86 имеет обратный порядок байтов, поэтому константы, напечатанные при дизассемблировании, должны быть заменены байтами.

person Jester    schedule 15.01.2013