2009-04-22

Linux kernel debugging

Всем известно, что в vmware 6-й ветки появилась возможность отлаживать ядро гостевой операционной системы. Для включения отладки необходимо в конфиг виртуальной машины (файл *.vmx) добавить строку debugStub.listen.guest32=1 либо debugStub.listen.guest64=1. Vmware откроет порт 8832 (или 8864 для 64-битных систем) на главной системе(хосте):
>netstat -an | grep 88
TCP 127.0.0.1:8832 0.0.0.0:0 LISTENING

Как видим, подключиться можно только с локалхоста. Используеться протокол gdb, соответственно, берём gdb (версию для Windows в сети найти не трудно), и подключаемся:
> gdb -q
(gdb) target remote localhost:8832

Для удобного ковыряния в ядре, потребуеться собрать ядро с отладочными сиволами, обчычно ядра, установленные в различных дистрибутивах по умолчанию собраны без отладочных символов (что и не удевительно, поскольку включение символов несколько увеличивает размер образа ядра). Чтобы пересобрать ядро используя текущюю рабочюю конфигурацию, переходим в каталог исходников ядра (обычно /usr/src/linux), и выролняем:
make oldconfig
make menuconfig

В меню включаем отладочные символы:
Kernel hacking  --->
[*] Compile the kernel with debug info

или "CONFIG_DEBUG_KERNEL=y" в конфиге ядра (/usr/src/linux/.config). На стадии конфигурирования ядра желательно отключить всё лишнее (например можно отключть поддержку IPv6, если она не нужна, и ненужные драйвера), и всё что возможно вкомпилить в ядро, а не в виде модулей. Однако netfilter и драйвера сетевых интерфейсов я бы посоветовал всё-таки собрать в виде модулей. Можно вместо make oldconfig, сделать make defconfig, что-бы создать минимальный конфиг по умолчанию для данной архитектуры, а потом в make menuconfig включать необходимые опции, и добавить нужные драйвера (lspci может в этом помоч). Далее собираем ядро:
make
make modules_install

Файл /usr/src/linux/vmlinux - это несжатый образ ядра, его переносим с гостевой системы на основную. Желательно так-же иметь на основной стсиеме исходные коды ядра соответсвующей версии. Кладём файл vmlinux на основную систему в папку где находяться исходники ядра (у меня D:\kernel\). Устанавливаем новое ядро и перезагружаем гостевую систему. Теперь можно спокойно отлаживать ядро загрузив в gdb несжатый образ ядра с отладочнымм символами:
> gdb -q
(gdb) target remote localhost:8832
<...>
(gdb) file vmlinux

P.S.
по этой ссылке http://wiki.opennet.ru/Linux_kernel_debug рекомендуют включить в ядре такие опции:
Kernel hacking  --->
[*] Compile the kernel with debug info
[*] Compile the kernel with frame pointers

2009-02-21

Права доступа Windows

Продолжаю записывать в этот блог разный мусор, который больше сохранить просто негде (потеряеться).
Измененме ACL в Windows, можно использовать когда нельзя ответить y/n (например при выполнении команд через функцию system() в php):
echo y | cacls file.txt /C /E /P Users:F

снятие атрибута "только чтение", который иногда очень мешает:
attrib -r * /S /D

2009-01-16

Юникс конфиги

Удобно так просматривать конфиги на юникс-машинах:
egrep -v "^$|#" ssh_config

из вывода будут убраны все пустые строки, а так-же строки, начинающиеся с '#'.

2008-12-20

Загрузка драйверов в Windows

Один из самых простых способов загрузить драйвер в Windows - использльзовать SCM (Service Control Manager). Для быстрой загрузки/выгрузки своих небольших драйверов, я набросал програмку. Програма создаёт службу(Service) типа SERVICE_KERNEL_DRIVER с именем test_driver (соответственно в реестре создаёться раздел HKLM/System/CurrentControlSet/Services/test_driver). Подробнее про cлужбы можно почитать на wasm.ru

//Service Control Programm
#include <windows.h>
#include <stdio.h>
#define MAX_L 256

char *sn="test_driver";
char *dn="test_driver";

int unload()
{
SC_HANDLE hSCM, hService;
SERVICE_STATUS status;

hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM == NULL){
printf("[!] Error in OpenSCManager\n");
return -1;
}
hService = OpenService(hSCM, sn , SC_MANAGER_ALL_ACCESS);

if(!hService){
printf("Error in hService\n");
return -1;
}
if(ControlService(hService, SERVICE_CONTROL_STOP, &status) != TRUE){
printf ("[!] Error in ControlService. Code: %.x\n",GetLastError());
return -1;
}
DeleteService(hService);
printf("stoped..\nUnloaded..\n");
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
return 1;
}

int load(char * path)
{
SC_HANDLE hSCM, hService;
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM == NULL){
printf("[!] Error in OpenSCManager\n");
return -1;
}

GetFullPathName(path,MAX_L,path,NULL);

hService = CreateService(hSCM, sn, dn, SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, path,
NULL, NULL, NULL, NULL, NULL);

if(StartService(hService,0,NULL)!=TRUE){
printf("[!] Error in StartService. Code: %.x\n",GetLastError());
return -1;
}
printf("Now driver loaded in kernel memory.\n");
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
return 1;
}

void usage(char * p){
printf("Load driver: %s l \nUnload driver: %s u",p,p);
exit(0);
}

int main(int argc, char * argv[])
{
int r = 0;
if(argc<2) usage(argv[0]);
switch(*argv[1])
{
case 'l':
if(argc!=3) usage(argv[0]);
r = load(argv[2]);
case 'u':
if(argc<2) usage(argv[0]);
r = unload();
default:
usage(argv[0]);
}
return r;
}

2008-12-12

SDT

Осваиваюсь с внутреним устройством Windows, вот, набросал кодес для получения данных из SDT. Например получим номер функции NtCreateProcessEx которая в Windows Vista SP1 находиться по адрессу 0x826a8fea, а в Windows XP SP2 - 0x805c5c32:

#include <ntddk.h>

extern PUSHORT NtBuildNumber;
extern PVOID KeServiceDescriptorTable;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegPath)
{
unsigned long t, t2, p, pNtCreateProcessEx;
int i,j;

switch(*NtBuildNumber){
case 2600: //winxp
pNtCreateProcessEx = 0x805c5c32;
break;

case 6001: //vista (at least sp1)
pNtCreateProcessEx = 0x826a8fea;
break;
}

DbgPrint("[+] Driver successfuly loaded\n");
DbgPrint("SDT addr: %x\n", KeServiceDescriptorTable);

t = *((PULONG)KeServiceDescriptorTable);
for (i=j=0;j<=391;i+=4,j++){
t2 = *((PULONG)(t+i));
if(t2 == pNtCreateProcessEx){
DbgPrint("NtCreateProcess index: %d addr:%x\n", j,t2);
}
}
return STATUS_DEVICE_CONFIGURATION_ERROR;
}

2008-08-19

Змейка на Си

Змейка на ncurses =) Для компиляции нужна библиотека ncursess, скорей всего есть по-умолчанию: gcc -lcurses snake.c -o snake
Есть глюк, если во время движения, поверуть в противоположную сторону - змейка сама в себя врежеться. Например, если при движении вверх, нажать вниз - то врежеться змейка в себя. Надо бы как-нибудь поправть. Кстати, мой рекорд - 64 =)

#include <curses.h>
#include <stdlib.h>

#define WH 25
#define WW 25

#define MAX_SNAKE 255

typedef struct{
int y;
int x;
} head_struct;

typedef struct snk_St{
int y;
int x;
struct snk_St *next;
} snk_s;

snk_s *snk;
head_struct set_food(){
head_struct food;
food.y=1+(int)(23.0 * (rand()/(RAND_MAX+1.0)));
food.x=1+(int)(23.0 * (rand()/(RAND_MAX+1.0)));
return food;
}

int main(){
head_struct body[MAX_SNAKE], food;
int lose=0;
char *space=" ";
WINDOW *my_win, *stats_win, *lose_win;
char *str="GAME OVER press F1 to quit";
initscr();
nonl();
noecho();
timeout(60);
curs_set(0);
start_color();
if(has_colors()){
init_pair(1,COLOR_GREEN,COLOR_BLACK);
init_pair(2,COLOR_CYAN,COLOR_BLACK);
}
stats_win=newwin(3,WW+10,1,2);
wbkgd(stats_win,COLOR_PAIR(1));

my_win=newwin(WH,WW,4,7);
wbkgd(my_win,COLOR_PAIR(1)|A_BOLD);

lose_win=newwin(3,(strlen(str)+4),14,4);
wbkgd(lose_win,COLOR_PAIR(2)|A_BOLD|A_BLINK);
box(lose_win,0,0);
body[0].y=2;
body[0].x=2;
box(my_win,0,0);
int old_c=66,c,food_c=0,score=1,b=0;
for(;;)
{
if(!food_c){
food=set_food();
food_c=1;
}


if (body[0].x==food.x && body[0].y==food.y){
score+=1;
if(score == 254) lose=1;
food_c=0;
}

c=getch();
if (old_c==65 && c==66) c=65;
if (old_c==66 && c==65) c=66;
if (old_c==67 && c==68) c=67;
if (old_c==68 && c==67) c=67;
(c==ERR)?(c=old_c):(old_c=c);
for(b=score+1;b!=0;b--){
body[b].y=body[b-1].y;
body[b].x=body[b-1].x;
}


switch(c){
case 65:
body[0].y-=1;
if(body[0].y==0) body[0].y=23;
break;

case 66:
body[0].y+=1;
if(body[0].y==24) body[0].y=1;
break;
case 67:
body[0].x+=1;
if(body[0].x==24) body[0].x=1;
break;
case 68:
body[0].x-=1;
if(body[0].x==0) body[0].x=23;
break;
}
for(b=score-1;b>3;b--){
if(body[0].y==body[b].y && body[0].x==body[b].x){
lose=1;
}

}
if(lose==1){
break;
}
mvwaddch(my_win,food.y,food.x,'F');
mvwaddch(my_win,body[0].y,body[0].x,'@');
mvwaddch(my_win,body[1].y,body[1].x,'*');
mvwaddstr(my_win,body[score].y,body[score].x,space);

mvwprintw(stats_win,1,1,"Score: %d; Food: Y=%.02d X=%.02d",score,food.y,food.x);
wnoutrefresh(stats_win);
mvwaddch(my_win,body[score].y,body[score].x,32);
wnoutrefresh(stats_win);

wnoutrefresh(my_win);
doupdate();
}
wclear(my_win);
wclear(stats_win);

mvwaddstr(lose_win,1,2,str);
wnoutrefresh(lose_win);
doupdate();
c=0;
for(;;){
c=getch();
if(c==80) break;
c=0;
}
endwin();
return 0;
}

Архив