Наши друзья
|
Подключение к запущенному процессу
Программа GDB обладает прекрасной возможностью подключаться и отключаться от запущенных процессов. Поскольку для большей части серверного программного обеспечения применяются достаточно сложные процедуры при запуске, то зачастую весьма сложно и неудобно запускать программы внутри отладчика.
Возможность подключения к запущенному процессу экономит массу времени. Прежде всего, следует определить идентификатор процесса (PID), отладку которого мы собираемся провести. Для программы Netscape I-Planet может потребоваться несколько попыток такого определения.
Чтобы подключиться к запущенному процессу с помощью GDB, запускаем команду gdb и затем вводим следующую команду после появления приглашения на ввод команды, где process-id — это идентификатор искомого процесса.
(gdb) attach process-id
После подключения к процессу следует воспользоваться командой continue с целью продолжить выполнение программы. Чтобы вернуться к приглашению на ввод команды, можно нажать комбинацию клавиш <Ctrl+C>.
(gdb) continue
Если процесс является многопоточным, то с помощью команды info можно просмотреть перечень всех запущенных потоков (безусловно, это не единственное предназначение этой команды).
(gdb) info |
threads |
|
|
|
|
|
|
|
|
90 |
Thread |
71 |
|
0xfebla018 |
in |
lwp |
sema |
wait () |
from /usr/lib/libc |
so |
1 |
8 9 |
Thread |
70 |
(LWP 14) |
0xfebl8224 |
in |
poll () from /usr/lib/libc.so.1 |
|
|
88 |
Thread |
69 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
87 |
Thread |
68 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/1ibthread |
so |
1 |
86 |
Thread |
67 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
85 |
Thread |
66 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
84 |
Thread |
65 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
83 |
Thread |
64 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
82 |
Thread |
63 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
81 |
Thread |
62 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
80 |
Thread |
61 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
79 |
Thread |
60 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
78 |
Thread |
59 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
77 |
Thread |
58 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
7 6 |
Thread |
57 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
75 |
Thread |
56 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
74 |
Thread |
55 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
73 |
Thread |
54 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
72 |
Thread |
53 |
|
0xfeb88014 |
in |
cond |
wait |
() from |
/usr/lib/libthread |
so |
1 |
Чтобы получить список всех функций в стеке вызовов, воспользуйтесь следую щей командой.
(gdb) info stack
#0 0xfedd9490 in _MD_getfileinfo64 ()
from /usr/local/iplanet/servers/bin/https/lib/libnspr4.so #1 0xfedd5830 in PR_GetFileInfo64 ()
from /usr/local/iplanet/servers/bin/https/lib/libnspr4.so #2 0xfeb62f24 in NSFC_PR_GetFileInfо ()
from /usr/local/iplanet/ serve г s/Ъ in/https/lib/libnsfc.so #3 0xfeb64588 in NSFC_ActivateEntry ()
from /usr/local/iplanet/servers/bin/https/lib/libnsfc.so #4 0xfeb63fa0 in NSFC_AccessFilename ()
from /usг/local/iplanet/servers/bin/https/lib/libnsfс.so #5 0xfeb62d24 in NSFC_GetFileInfо ()
from /usг/local/iplanet/servers/bin/https/lib/libnsfс.so #6 0xffle6cdc in INTrequest_info_path ()
from /usr/local/iplanet/servers/bin/https/lib/libns-httpd40.so ... _MD_getfileinfo64
В данном примере текущей функцией является функция _MD_getf ileinfo64, вызванная функцией PR_GetFIleInfo64, которая в свою очередь была вызвана функцией NSFC_PR_GetFileInfо и т.д. Стек вызовов позволяет проследить вызов функции и определить "путь" исполнения кода в программе.
Использование программы Truss для моделирования исследуемого процесса на платформе Solaris
ДЛЯ восстановления исходного кода исполняемых файлов I-Planet мы скопировали основные исполняемые файлы и связанные с ними библиотеки на стандартную рабочую станцию Windows 2000, где была установлена программа IDA-Рго. Цель заключалась в исследовании обращений к функциям файловой системы и отслеживании кода для обработки адресов URL, чтобы удаленно определить возможные пути выполнения программы в файловой системе. Этот пример может использоваться в качестве модели для поиска уязвимых мест во многих пакетах программного обеспечения. С помощью IDA можно восстановить исходный код приложений на многих UNIX-платформах, a GDB позволяет выполнить процесс восстановления практически на всех доступных платформах.
При восстановлении исходного кода Web-сервера первоочередная задача заключается в поиске подпрограмм, которые обрабатывают данные универсальных идентификаторов ресурса (Uniform Resource Identifier — URI). Данные URI предоставляются удаленными пользователями. При наличии уязвимых мест их легче всего использовать во вредоносных целях. Среди огромного количества вызовов функций API, которые выполняются каждую секунду, очень сложно выявить наиболее важные. К счастью, существуют мощные средства, с помощью которых можно смоделировать запущенное приложение. В нашем случае для отслеживания подпрограмм, обрабатытающих адреса URI, используется отличная Solaris-программа под названием Truss1.
На платформе Solaris 8 программа Truss позволяет отследить библиотечные вызовы API запущенного процесса. Это очень удобно для определения того, какие вызовы используются при определенных ситуациях в программе. Чтобы понять, какая часть кода сервера I-Planet обрабатывает данные, мы подключили Truss к основному процессу и создали "журналы" вызовов, использовавшихся при обработке Web-запросов (при работе на другой платформе, отличной от Solaris, можно использовать подобное средство под названием It race. Это бесплатная программа с открытым исходным кодом, которая работает на многих платформах).
Пользоваться Truss очень просто, и ее можно подключать и отключать по отношению к запущенному процессу. Для подключения к запущенному процессу нужно найти его идентификатор и выполнить следующую команду.
# truss -u *:: -vail -xall -p process_id
Если нужны только определенные вызовы функций API, можно совместить использование команд truss и grep.
# truss -u *:: -vail -xall -p 2307 2>&1 | grep anon
Приведенная выше команда позволяет отследить процесс с идентификатором 2307 и показать только те используемые им вызовы, в которых присутствует подстрока anon. Без труда можно изменить grep для игнорирования определенных вызовов. Это весьма удобно, поскольку можно узнать обо всех вызовах, кроме надоедливых вызовов poll и read.
# truss -u *:: -vail -xall -p 2307 2>&1 | grep -v read I grep -v poll
Обратите внимание на необходимость использования тега, поскольку Truss не выводит данные на стандартное устройство вывода (stdout).
Результат выполнения команды будет выглядеть примерно следующим образом.
/67: <- libns-httpd40: OFTutil strftime convPciTCc() = 50
/67:: -> libns-httpd40: 0FT util strftime conwP<caTSte(((OxffOedE3412?.. 0x2, 0x2,
0x3 0)
/67: <- libns-httpd40: OBFEtuttil strftime convPciTCc() = 0;xff2ed345
/67: <- MbnKHhttpdfflO:: INTutilL_sstrftime () = 2 0
/67: -> libns-httpd40:INTsystem_strdup(((Sxtf^edffi330,, 0x9» 0x41, 0x50)
/67: -> libns-httpd40:I^Tpo>ol_strdu^«0x^e0KaE0^^, 0xff2edt3330, 0x0, 0x0)
/67: -> libc^:sttrlen^(^0xffl^jd^:ETO, 0x0, 0x0, 0x0)
/67: <- libc:strlesm(()) = 20
/67: <- libns-httpd40:INTpool=strdupO - 0x9f8bl0
/67: <— lib^j-httpd40:INTsystem=strdupO - 0x9f8bl0
/67: <- riib^!-httpd40^1timei^^ecurr_strftime_logfmt() = 0x9f8bl0
/67: -> libc:strcpy(0xf7400710, 0x9f8bl0, 0x0, " 0sx7efefeff)
/67: <- lilbc:strcpy() = 0xf7400710
/67: -> libc:strlen(0xf7400710, 0x9f8b28, 0xf7400710, 0x0)
/67: <- libc:strlen() = 20
/67: -> libc:strlen(0x9f4f48, 0x34508f, 0x0, 0x7efefeff)
/67: <- libc:strlen() = 25
В этом (отчете токазаны ввыиовы функций API, которые треализуются процессом с идентификатором233077. Программа Tlruss делаеет отстрыт в тексте, чтобы ™|делить вложенные вызовы функций. Использование экземпляров запущенных приложений при обработке «определенных запросов и поолеедующе исследование тррассировки вызову является «отличным методом (восстановления исходного кода. |