Переполненные байты отличаются от тех, что я вижу на GDB? - PullRequest
1 голос
/ 12 марта 2020

Я пытаюсь выполнить вызов ProtoStar stack5 . Я знаю решение (после написания), но я пытаюсь предложить другой подход.

Вот исходный код программы, для которой мы пытаемся выполнить шеллкод:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  char buffer[64];

  gets(buffer);
}

Итак, чтобы посмотреть, что происходит в регистрах, я делаю следующее:

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7b0:     0x41414141      0xbffff800      0xbffff85c      0xb7fe1848
0xbffff7c0:     0xbffff810      0xffffffff
(gdb) p $ebp
$1 = (void *) 0xbffff7a8
(gdb)

Хорошо, я переполняю адрес возврата 41414141. Как и ожидалось. Теперь я хочу изменить адрес возврата на следующие 4 байта, так что

00xbffff7a8: |saved frame pointer| - | return address| - |shellcode part 1| - |...| - |shellcode part n|

Однако, когда я пытаюсь записать 76 "41", а затем адрес 0xbffff7a8 + 4 (который 0xbffff7b0), он продолжает писать не то, что нужно. Вот что я ввожу:

41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141b0f7ffbf

Обратите внимание, что мы находимся в системе с прямым порядком байтов.

Однако, когда я ввожу это (как ASCII), это то, что я вижу на $ esp и $ ebp:

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA°÷ÿ¿
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff760:     0xbffff770      0xb7ec6165      0xbffff778      0xb7eada75
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0xb7c3b0c2
0xbffff7b0:     0xbfc2bfc3      0xbffff800      0xbffff86c      0xb7fe1848
0xbffff7c0:     0xbffff820      0xffffffff ...
(gdb) p $ebp
$1 = (void *) 0xbffff7a8

Как видите, 0xb7c3b0c2 записывается вместо ожидаемого 0xbffff7b0

Кто-нибудь знает, почему это так?

ПРИМЕЧАНИЕ. Я понимаю, что адрес Я действительно хотел 0xbffff7a c, а не 0xbffff7b0. Я исправлю это, но это не изменит проблему, с которой я столкнулся.

1 Ответ

0 голосов
/ 30 марта 2020

Итак, я решил опубликовать эту проблему на Subreddit LiveOverflow , и мне было указано направление этого видео от LiveOverflow.

Видео многое объяснит лучше меня, но по сути, python2 и python3 не печатают hex в ascii одинаково. Python3 вставляет дополнительные символы, в то время как python2 печатает необработанную шестнадцатеричную строку.

Я настоятельно рекомендую вам посмотреть видео, поскольку оно объясняет его с глубиной.

Это ответ на другой вопрос здесь на SO, на который отвечает @ d sh, также объясняет это:

Последовательность байтов C3 BE - это кодированное UTF-8 представление символа U + 00FE.

Python 2 обрабатывает строки как последовательность байтов, а не символов. Таким образом, \ xfe - это строковый объект, содержащий один байт.

В Python 3 строки представляют собой последовательности символов (Unicode). Таким образом, код '\ xfe' является строкой, содержащей один символ. Когда вы печатаете строку, она должна быть закодирована в байтах. Поскольку ваша среда выбрала кодировку по умолчанию UTF-8, она была закодирована соответствующим образом.

Способ ее решения зависит от ваших данных. Это байты или символы? Если это байты, то измените код, чтобы сообщить интерпретатору: print (b '\ xfe'). Если это символы, но вы хотели использовать другую кодировку, закодируйте строку соответствующим образом: print ('\ xfe'.encode (' latin1 ')).

...