🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: alt.pl.fan.gopher
Article #13551

Re: Upload...

#13551
From: Adam Wysocki
Date: Wed, 15 Jan 2003 23:08
320 lines
15063 bytes
15.01.03 Puck wrote:

> Może nie takie hello world... W sumie tego nigdy
> nie udało mi się zrobić, bo nie mogłem się zdecydo-
> wać, jak wyświetlić tekst. :)

Na wspak :P

> W każdym razie jest to mój trzeci programik, ale
> pierwszy tak na prawdę przydatny i skończony.

...piszący hello world ;P

> Najpierw było coś, co miało winampa obsługiwać, 
> ale nie dokończyłem, bo miałem stare Delphi, 
> a poza tym stanąłem w martwym punkcie. Może 
> kiedyś zabiorę się za to od nowa.

Ahh, to api Windows, pozwalające wysłać dowolny komunikat do dowolnego 
okienka bez jakiejkolwiek autentykacji, oraz zapisanie dowolnej strony 
pamięci, też bez jakiegokolwiek zająknięcia, jak ja kocham ten system 
:))) Może coś się zmieniło od czasów Win95/98, ale kiedyś tak było.

A Linux jest taki kochany...

Napiszmy krótki programik w C. Bez zagłębiania się w szczegóły, 
wywołujemy go przez podanie w linii poleceń liniowego adresu 
w pamięci bajtu, który ma próbować odczytać, po czym zapisać 
odczytaną wartość.

int main (int argc, char **argv)
{
 char *ptr, bt;
 if (argc < 1)
  return 0;
 ptr = (char *) strtol(argv[1], 0, 0);
 printf ("Pobieram bajt...\n");
 bt = ptr[0];
 printf ("Zapisuję bajt...\n");
 ptr[0] = bt; 
 return 0;
}

Entery w każdej linii, bo informacja o segfaulcie przechodzi do początku 
linii bez jej wysunięcia.

Weźmy jakikolwiek proces systemowy, np. sysloga.

$ cd /proc/`/sbin/pidof syslogd`/;pwd
/proc/565

Zobaczmy, jak się ulokował w pamięci.

$ cat maps
08048000-0804e000 r-xp 00000000 03:02 127143     /sbin/syslogd
0804e000-0804f000 rw-p 00006000 03:02 127143     /sbin/syslogd
0804f000-08055000 rwxp 00000000 00:00 0
40000000-40012000 r-xp 00000000 03:02 126666     /lib/ld-2.2.5.so
40012000-40013000 rw-p 00012000 03:02 126666     /lib/ld-2.2.5.so
40013000-40014000 rw-p 00000000 00:00 0
4001d000-4013b000 r-xp 00000000 03:02 126675     /lib/libc-2.2.5.so
4013b000-40140000 rw-p 0011e000 03:02 126675     /lib/libc-2.2.5.so
40140000-40144000 rw-p 00000000 00:00 0
4014e000-40157000 r-xp 00000000 03:02 126699     /lib/libnss_files-2.2.5.so
40157000-40158000 rw-p 00008000 03:02 126699     /lib/libnss_files-2.2.5.so
bfffc000-c0000000 rwxp ffffd000 00:00 0

Jak to słodko wygląda :)) Literki w drugiej kolumnie to prawa dostępu 
do podanego po lewej stronie obszaru pamięci, nas interesuje w (zapis). 
Teraz spróbujmy coś mu namieszać w pamięci, w której nie możemy mieszać 
(nie ma literki w). Zezwalamy na generowanie coredumpów...

$ ulimit -c unlimited

I odpalamy na pierwszym bajcie obszaru, do którego nie możemy pisać. 
Niech będzie to pierwszy obszar, czyli 08048000.

$ zrzutek 0x08048000
Pobieram bajt...
Zapisuję bajt...
Segmentation fault (core dumped)

Ha! :) Zobaczmy czemu...

$ gdb zrzutek core* (gwiazdka, bo mam w /etc/sysctl.conf 
kernel.core_uses_pid = 1, nieważne)

[chrup]

Błąd wystąpił na:

#0  0x0804849c in main ()

Piszemy disassemble...

Dump of assembler code for function main:
[chrup masa kodu]
0x804849c <main+92>:    mov    %al,(%edx)
[kolejne chrup]
End of assembler dump.

Przypatrz się zostawionej przeze mnie linijce. Tam był procesor, 
kiedy został wygenerowany wyjątek ochrony (wystąpiło naruszenie 
ochrony pamięci). Tak się składa, że ta linia powoduje wpisanie 
czegoś pod pewien adres w pamięci. Widać coś (hehe ;>) próbowało 
wpisać coś do nieuprawnionej strony pamięci, ale odpowiednio ustawiony 
przez jądro procesor wychwycił to, wygenerował wyjątek ochrony (page 
fault exception), zostało to przechwycone przez jądro (konkretnie 
handler o wdzięcznej nazwie do_page_fault(struct pt_regs *regs, 
unsigned long error_code), więcej informacji w źródłach jądra, 
polecam lekturę arch/i386/mm/fault.c), handler zrobił wiele 
miłych rzeczy, typu pobranie evil adresu evil strony z rejestru 
CR2, sprawdzenie, czy ten adres jest w obszarze pamięci danego 
procesu (swoją drogą na pierwszy rzut oka jest to IDIOTYCZNIE 
rozwiązane, ale jak się wczytasz to zobaczysz, że czasami goto 
lepiej się kompilują), jeśli tak to prawdopodobnie strona nie 
była wyswappowana, zabezpieczona przed zapisem, albo coś podobnego, 
zresztą mniejsza z tym. Wspomnę tylko, że wtedy są sprawdzane nawet 
szczegóły typu co się stało - czy nie ma takiej strony, czy nastąpił 
wyjątek ochrony jakiejś istniejącej strony, czy był to wyjątek zapisu, 
odczytu, wykonywania, czy czego, czy był to błąd wywołany przez proces 
jądra, użytkownika, itp, oraz robione naprawdę różne inteligentne rzeczy. 
Mniejsza z tym. Po wielu zmaganiach jądro wysłało SIGSEGV do procesu (zrób 
killall -SEGV `/sbin/pidof nazwa`, wynik będzie ten sam, czyli zrzut 
aktualnego stanu procesu - oczywiście jeśli masz uprawnienia do wysyłania 
sygnałów procesowi), i dalej tak ładnie to się potoczyło.

Innymi słowy zestaw jądro+CPU nie pozwoli na skrzywdzenie procesu.

Już zrozumiałeś?

To teraz wyobraź sobie, że jądro Windows wszystkie alokowane strony pamięci 
domyślnie zaznacza jako w, czyli dowolny proces może tam pisać ile chce. 
Zresztą jest tak nie tylko z pamięcią, tak samo jest z przestrzenią I/O 
oraz z wywoływaniem przerwań trybu rzeczywistego. Kiedyś, jak byłem 
jeszcze linuksianym nielotem, mało wiedziałem o możliwościach trybu 
chronionego CPU, ale całkiem dobrze znałem się na pracy w trybie 
rzeczywistym (np. DOS), bawiłem się systemem, zaglądałem tam, gdzie 
na pewno nikt o zdrowych zmysłach nie powinien, i w pewnym momencie 
poczułem się na tyle mocny, że postanowiłem odkryć dziurę :)) Pomyślałem, 
że skoro nie da się odczytać pliku procedurami systemowymi, pewnie 
nie da się też przez dostęp przez /dev/hda (nie dało, less -f 
/dev/hda dawało permission denied), pewnie nie da się także przez 
BIOS (int 13h, ale nie sprawdzałem tego pod Linuksem), to pewnie 
da się bezpośrednimi odwołaniami do kontrolera dysków. Jakie było 
moje zdziwienie jak zobaczyłem, że przy próbie komunikacji z kontrolerem 
występuje segfault, nie jesteś sobie w stanie nawet wyobrazić, jak mi 
wtedy szczęka opadła :)) Dopiero potem dowiedziałem się, co to są 
iopermy, itp. i doceniłem pracę projektantów procesorów i developerów 
Linuksa (chociaż wspomniany wyżej kod napisał Linus Torvalds, ojciec 
systemu).

> Drugim programikiem był kalkulator (tzn dwa text
> fieldy, które były sumowane). Idea została stwo-
> rzona przez mojego informatyka, a moja inwencja
> polegała na tym, że wszystko robiłem sam (to by-
> ła pierwsza lekcja o Delphi) i dodawałem jakieś
> głupie bajerki (np. ProgresBar - dodawanie dwóch
> liczb trwało ok. 3 sekund).

Szybko :)

> Teraz to. Co, czyli właściwie co? Programik, 
> który sprawdza, czy pliki wymagają aktualizac-
> ji, i.e. jeśli timestamp danego pliku nie zga-
> dza się z wcześniej zapisanym (albo z zerem),
> jest wrzucany do osobnego katalogu...

Który timestamp? Utworzenia, dostępu, zmiany? E, no tak, to FAT... :)

Znowu źródła jądra, tym razem plik nagłówkowy.

$ less /usr/src/linux-2.4/include/linux/ext2_fs.h

[chrup]

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
        __u16   i_mode;         /* File mode */
        __u16   i_uid;          /* Low 16 bits of Owner Uid */
        __u32   i_size;         /* Size in bytes */
        __u32   i_atime;        /* Access time */
        __u32   i_ctime;        /* Creation time */
        __u32   i_mtime;        /* Modification time */
        __u32   i_dtime;        /* Deletion Time */
        __u16   i_gid;          /* Low 16 bits of Group Id */
        __u16   i_links_count;  /* Links count */
        __u32   i_blocks;       /* Blocks count */
        __u32   i_flags;        /* File flags */
        union {
                struct {
                        __u32  l_i_reserved1;
                } linux1;
                struct {
                        __u32  h_i_translator;
                } hurd1;
                struct {
                        __u32  m_i_reserved1;
                } masix1;
        } osd1;                         /* OS dependent 1 */
        __u32   i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
        __u32   i_generation;   /* File version (for NFS) */
        __u32   i_file_acl;     /* File ACL */
        __u32   i_dir_acl;      /* Directory ACL */
        __u32   i_faddr;        /* Fragment address */
        union {
                struct {
                        __u8    l_i_frag;       /* Fragment number */
                        __u8    l_i_fsize;      /* Fragment size */
                        __u16   i_pad1;
                        __u16   l_i_uid_high;   /* these 2 fields    */
                        __u16   l_i_gid_high;   /* were reserved2[0] */
                        __u32   l_i_reserved2;
                } linux2;
                struct {
                        __u8    h_i_frag;       /* Fragment number */
                        __u8    h_i_fsize;      /* Fragment size */
                        __u16   h_i_mode_high;
                        __u16   h_i_uid_high;
                        __u16   h_i_gid_high;
                        __u32   h_i_author;
        union {
                struct {
                        __u8    l_i_frag;       /* Fragment number */
                        __u8    l_i_fsize;      /* Fragment size */
                        __u16   i_pad1;
                        __u16   l_i_uid_high;   /* these 2 fields    */
                        __u16   l_i_gid_high;   /* were reserved2[0] */
                        __u32   l_i_reserved2;
                } linux2;
                struct {
                        __u8    h_i_frag;       /* Fragment number */
                        __u8    h_i_fsize;      /* Fragment size */
                        __u8    l_i_frag;       /* Fragment number */
                        __u8    l_i_fsize;      /* Fragment size */
                        __u16   i_pad1;
                        __u16   l_i_uid_high;   /* these 2 fields    */
                        __u16   l_i_gid_high;   /* were reserved2[0] */
                        __u32   l_i_reserved2;
                } linux2;
                struct {
                        __u8    h_i_frag;       /* Fragment number */
                        __u8    h_i_fsize;      /* Fragment size */
                        __u16   h_i_mode_high;
                        __u16   h_i_uid_high;
                        __u16   h_i_gid_high;
                        __u32   h_i_author;
                } hurd2;
                struct {
                        __u8    m_i_frag;       /* Fragment number */
                        __u8    m_i_fsize;      /* Fragment size */
                        __u16   m_pad1;
                        __u32   m_i_reserved2[2];
                } masix2;
        } osd2;                         /* OS dependent 2 */
};

Ale fat przy tym blado wygląda... :)

$ less /usr/src/linux-2.4/include/linux/msdos_fs.h

[chrup]

struct msdos_dir_entry {
        __s8    name[8],ext[3]; /* name and extension */
        __u8    attr;           /* attribute bits */
        __u8    lcase;          /* Case for base and extension */
        __u8    ctime_ms;       /* Creation time, milliseconds */
        __u16   ctime;          /* Creation time */
        __u16   cdate;          /* Creation date */
        __u16   adate;          /* Last access date */
        __u16   starthi;        /* High 16 bits of cluster in FAT32 */
        __u16   time,date,start;/* time, date and first cluster */
        __u32   size;           /* file size (in bytes) */
};

:)

> ....po co? Żeby w łatwy sposób sprawdzić, któ-
> re pliki trzeba update'ować na serwerze.

Sort by mtime? ;D

> BTW, nie wiem jeszcze jaka jest zależność pomię-
> dzy zwracanymi wartościami (hs2 a Delphi). Jedna
> wartość jest Unixowym formatem czasu, druga - nie
> pamiętam, w każdym razie są mniej więcej w sto-
> sunku 10:7. :o

Może jedna odczytuje z RTC a druga z zegara systemowego, 
praktyka pokazuje, że nawet pod DOSem te zegary lubią 
się bahłardzo różnić :P

A poważnie, sprawdź różnicę między tymi wartościami, poczekaj 
chwilę i znowu sprawdź, jeśli będzie niezmienna to może jest 
inna względność liczenia, wprawdzie pod Linuksem czas zaczął 
płynąć od stycznia 1970 (Wielki Wybuch, zwany czasami apcoh, 
erm, epoch), a pod DOSem dziesięć lat później... Albo jeden 
zwraca czas UTC, drugi CET, trzeci ARC, czwarty SRM, itp.

> Jak dostanę coś, co pakuje exeki,

pklite? :)

> albo dowiem sie, jak zoptymalizować kompilację,

Use the assembly, luke ^_^ Chociaż wszystko zależy od ciebie, znam 
idiotów, którzy przestrzeń pod stos (mowa oczywiście o exekach MZ) 
wypełniali losowymi wartościami... Gdy spytałem, czemu nie zostawią 
zer albo w ostateczności, celami debuggerskimi, nie wpiszą tam Hack 
the Stack, odpowiadali `a bo tak jest ciekawiej'. Wtedy już mi wszystko 
opadło...

-- 
Pozdrowienia z Warszawy * Adam `gophi' Wysocki * gophi@studio.tpi.pl
GG# 1234 * RLU# 265791 * ICQ# 173653642 * GSM# +48505439030 * CB# 33
Jesteś Gophim :) Jedynym w swoim rodzaju, niepowtarzalnym (C) Muszek
Masz krok dresiarza, który chciałby komuś wpier*olić. ;) (C) zwiecha
Technical Details
Message-ID: <gophi.1245333271@gophi.nascom.nasa.gov>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.atcom.net.pl!wysocki.lodz.pdi.net!gophi.nascom.nasa.gov!gophi
References: <20030115.12958@news.blade.net>

Show Full Headers
Complete Article Headers
Newsgroups: alt.pl.fan.gopher
Subject: Re: Upload...
Date: Thu, 16 Jan 2003 00:08:29 +0100
Lines: 321
References: <20030115.12958@news.blade.net>
Mime-Version: 1.0
X-Trace: localhost.localdomain 1042672110 5102 127.0.0.1 (15 Jan 2003 23:08:30 GMT)
NNTP-Posting-Date: Wed, 15 Jan 2003 23:08:30 +0000 (UTC)
In-Reply-To: <20030115.12958@news.blade.net>
From: Adam Wysocki <adam@wysocki.lodz.pdi.net>
Reply-To: gophiczq <gophi@studio.tpi.pl>
Organization: PFT Hacking Group
NNTP-Posting-Host: gophi.nascom.nasa.gov
X-Complaints-To: news@aramin.one.pl
User-Agent: Pine 4.44 / Red Hat Linux 7.3 (Valhalla) / Kernel 2.4.18-3
X-Geek-Code-1: GAT d? s+: a1985 C++ UL+++ P+ L+++ E---- W- N++ K- w--- !O M--
X-Geek-Code-2: V-- PS+ PE+ Y-- PGP- t- !5 X+ R- tv- b+ DI- D+ G e- h* r% y*
X-Geek-Code-3: v3.12
X-License: This message is PPL-Licensed, details on http://ppl.7thGuard.net/
X-Hardcore-User: pine
X-No-Archive: yes
X-Uwaga: O ile nie jest zaznaczone inaczej, poglady wyrazone przeze mnie          sa moimi wlasnymi pogladami i moga, ale nie musza, byc zgodne          z pogladami moich bylych, obecnych oraz przyszlych pracodawcow.
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!news.atcom.net.pl!wysocki.lodz.pdi.net!gophi.nascom.nasa.gov!gophi
Message-ID: <gophi.1245333271@gophi.nascom.nasa.gov>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit