Адреса памяти стека в шеллкоде

Я читал базовую статью о написании шелл-кода (выполнение с использованием метода стека) здесь: http://hackoftheday.securitytube.net/2013/04/demystifying-execve-shellcode-stack.html

На шаге 6: вставляется нулевой символ, потому что строка "/bin/sh" завершается нулем. После этого он проталкивает строку "/bin/sh" в обратном порядке.

Почему строка помещается в стек в обратном порядке и почему нулевой символ, завершающий строку, помещается «перед» помещением строки в стек?


person user720694    schedule 18.05.2013    source источник
comment
Просто совет. Если вы хотите, чтобы вопрос привлек больше людей, которые могли бы помочь, я предлагаю включить больше деталей в сам вопрос, а не ссылаться на внешний источник. Потому что, как только такой источник заканчивается, вопрос остается вне контекста.   -  person jwaliszko    schedule 19.05.2013
comment
@JaroslawWaliszko Спасибо. я буду иметь это в виду.   -  person user720694    schedule 19.05.2013


Ответы (1)


Строка, которая должна быть помещена в стек, выглядит следующим образом:

//bin/sh + '\0'(null terminator) + alignment(3 additional null characters)  -   gives 3 DWORDs (12 bytes)

Для этого мы должны выполнить набор инструкций в правильном порядке:

xor     eax, eax        ;zero out full 32 bits of eax register
push    eax             ;0x00000000
push    0x68732f6e      ;hs/n
push    0x69622f2f      ;ib//

Почему именно в таком порядке?

Из-за природы стека. Элементы должны быть помещены в него в обратном порядке, чтобы в дальнейшем правильно считываться из него. Стек — это структура данных с порядком первым пришел, последним вышел (FILO) (в отличие от кучи). Это означает, что первый элемент, который помещается в стек, является последним элементом, который выходит из него. По мере изменения размера стека он увеличивается в сторону более низких адресов памяти:

                        memory
.---------------.-- 00  <-- top    / low addresses
|       .       |       x+1
|      /|\      |       x+2
|       |       |        .
|     stack     |        .
|grows up toward|        .
|lower addresses|       x+n
'---------------'-- FF  <-- bottom / high addresses

А как насчет этих двух двойных слов: 0x68732f6e (hs/n) и 0x69622f2f (ib//)? Как они связаны с //bin/sh ?

Глядя на 0x68732f6e, мы можем увидеть эффект реверсирования показанного байта за байтом, фактически сохраненного в памяти, 4 байта: 0x6e 0x2f 0x73 0x68 (n/sh). Это связано с архитектурой IA-32, специфичной для порядок байтов, который необходимо учитывать при ручном добавлении байтов в стек. В процессоре x86 значения хранятся в порядке следования байтов little endian (в отличие от big endian в процессорах SPARC), что означает, что младший байт сохраняется первым (младший конец идет первым):

byte3 byte2 byte1 byte0

будет располагаться в памяти следующим образом:

base address+0   byte0
base address+1   byte1
base address+2   byte2
base address+3   byte3

Итак, наконец, чтобы визуализировать, как заполняется пространство памяти, посмотрите ниже:

.---------  push    eax             ;0x00000000
|   .-----  push    0x68732f6e      ;hs/n           bytes reversed
|   |   .-  push    0x69622f2f      ;ib//           bytes reversed 
|   |   |                                       
|   |   |      register                     
|   |   '>  |69|62|2f|2f| (ib//)      memory
|   |        |  |  |  |                 ..  
|   |        |  |  |  '------->     x:  2f  '/'
|   |        |  |  '---------->   x+1:  2f  '/'
|   |        |  '------------->   x+2:  62  'b'
|   |        '---------------->   x+3:  69  'i'
|   |          little endian    
|   |                   
|   '---->  |68|73|2f|6e| (hs/n)      
|            |  |  |  | 
|            |  |  |  '------->   x+4:  6e  'n'
|            |  |  '---------->   x+5:  2f  '/'
|            |  '------------->   x+6:  73  's'
|            '---------------->   x+7:  68  'h'
|
'-------->  |00|00|00|00| (\0\0\0\0)
             |  |  |  |                 
             |  |  |  '------->   x+8:  00  '\0'
             |  |  '---------->   x+9:  00  '\0'
             |  '------------->   x+10: 00  '\0'
             '---------------->   x+11: 00  '\0'
                                        ..

Вы можете проверить его с помощью gdb:

(gdb) x/12b $sp
0xbfb530b0:     0x2f    0x2f    0x62    0x69    0x6e    0x2f    0x73    0x68
0xbfb530b8:     0x00    0x00    0x00    0x00
(gdb) x/12c $sp
0xbfb530b0:     47 '/'  47 '/'  98 'b'  105 'i' 110 'n' 47 '/'  115 's' 104 'h'
0xbfb530b8:     0 '\0'  0 '\0'  0 '\0'  0 '\0'
(gdb) x/3w $sp
0xbfb530b0:     0x69622f2f      0x68732f6e      0x00000000
person jwaliszko    schedule 19.05.2013