Kirjoittaja: Antti Laaksonen
Kirjoitettu: 16.01.2008 – 16.01.2008
Tagit: ohjelmointitavat, koodi näytille, vinkki, DOS
Henkilötunnuksen tarkistus on ohjelmointiväen kansanhuvia, vaikka harva ohjelma pääsee loppujen lopuksi tositoimiin tuntemattomien henkilötunnusten tarkistuksessa.
Tässä on DOS-ympäristössä toimiva assembly-ohjelma, joka lukee käyttäjältä henkilötunnuksen alkuosan ja lisää sen perään oikean tarkistusmerkin. Ohjelman voi kääntää nasm-kääntäjällä seuraavalla komennolla:
nasm -f bin hetu.asm -o hetu.com
Henkilötunnuksen tarkistusmerkki lasketaan muodostamalla henkilötunnuksen alkuosasta yhdeksännumeroinen luku, jakamalla tämä luku 31:llä ja katsomalla taulukosta jakojäännöstä vastaava tarkistusmerkki. Tarkka selostus laskutavasta on esim. Väestörekisterikeskuksen sivulla:
http://www.vaestorekisterikeskus.fi/vrk/home.nsf/pages/32C708B9CA6C5824C2256CB70038D048
Assembly-ohjelmaan kuuluu kaksi aliohjelmaa, jotka lukevat käyttäjältä yhden numeron ja välimerkin. Kun numerot luetaan yksi kerrallaan, luvun suuruus saadaan selville kertomalla aiemmin luettu osa 10:llä ja lisäämällä siihen uusi numero. Kuitenkin ainoa kiinnostava tieto on luvun jakojäännös 31:llä, minkä vuoksi pidetään kirjaa vain muodosteilla olevan luvun jakojäännöksestä 31:llä.
Tässä astuu kuvaan ohjelmointitemppu, jolla vältetään hankalat MUL- ja DIV-komennot. Aputaulukkoon on laskettu etukäteen, miten luvun jakojäännös 31:llä muuttuu, kun luku kerrotaan 10:llä. Tällä tavalla 10:llä kertomiseksi riittää noutaa taulukosta uusi jakojäännös. Uusi numero lisätään tavalliseen tapaan lukuun, mutta jos näin saatu luku on 31 tai suurempi, luvusta vähennetään 31.
Esimerkiksi luvun muodostuksessa saattaa esiintyä tilanne, jossa on luettu numerot 241 ja nyt vuorossa on numero 2. Lopputulos on tietysti 2412, jonka jakojäännös 31:llä on 25. Tässä ohjelmassa kuitenkin muistissa on 241:n asemesta pelkkä saman luvun jakojäännös 31:llä, joka on 24. Aputaulukkoon on kirjattu, että 10:llä kertominen tuottaa uudeksi jakojäännökseksi 23. Tähän pitää enää lisätä luku 2, jolloin jakojäännös on 25 ja tulos täsmää.
Tarvittavan aputaulukon voi laatia esim. tällä QBasic-ohjelmalla:
FOR i% = 0 TO 30 PRINT i%, (i% * 10) MOD 31 NEXT
Saattaa herätä kysymys, mitä järkeä moisen aputaulukon käytössä on. Tässä tapauksessa koodi hieman lyhentyy ja vältytään kertolaskuilta ja jakolaskuilta. Kuitenkin tarvitaan ylimääräinen taulukko muistia kuluttamaan. 10:llä kertominen ja 31:llä jakaminen eivät ole kaikesta huolimatta kovin monimutkaisia toimintoja, joten kenties tällä kertaa taulukon laatiminen on hieman liioittelua. Mutta jos pitäisi suorittaa vastaavassa tilanteessa jokin monimutkainen lasku (edelleen jakojäännöksillä), taulukosta voisi olla paljon hyötyä.
Ohjelma käyttää DOSin keskeytyksiä merkin lukuun, merkin tulostukseen ja ohjelman sulkemiseen. Keskeytysten toimintaan voi perehtyä esim. seuraavassa osoitteessa:
http://heim.ifi.uio.no/~stanisls/helppc/idx_interrupt.html
org 100h xor bx, bx ; nollataan laskuri call numero ; luetaan 6 numeroa call numero call numero call numero call numero call numero call vali ; luetaan välimerkki call numero ; luetaan 3 numeroa call numero call numero mov dl, [merkit+bx] ; haetaan tarkistusmerkki mov ah, 02h ; näytetään tarkistusmerkki int 21h mov ax, 4c00h ; poistutaan ohjelmasta int 21h numero: mov bl, [kertot+bx] ; kerrotaan laskuri 10:llä mov ah, 01h ; luetaan numeromerkki int 21h sub al, '0' ; puretaan ASCII-koodi add bl, al ; lisätään numero laskuriin cmp bl, 31 ; vähennetään tarvittaessa 31 jl valmis sub bl, 31 valmis: ret vali: mov ah, 01h ; luetaan välimerkki int 21h ret ; henkilötunnuksen tarkistusmerkit merkit db "0123456789ABCDEFHJKLMNPRSTUVWXY" ; 10:llä kertomisen vaikutus laskuriin kertot db 0,10,20,30,9,19,29,8,18,28,7,17,27,6,16,26, db 5,15,25,4,14,24,3,13,23,2,12,22,1,11,21
Oho. Mitä muuta Asm ohjelmointiin tarvitsee kuin OllyDbg:N?
Käännetty ohjelma (133 tavua) on osoitteessa:
http://koti.mbnet.fi/pllk/muut/hetu.com (päivitetty 17.1.)
Jakke1: Sopiva kääntäjä (esim. nasm) ja tekstieditori riittävät.
Ihan kiva "lisä" vinkkiin tuo jakojäännösten taulukoiminen, jolloin noiden, ei ehkä hankalien, mutta aikaavievien kerto- ja jakolaskujen tarve poistuu.
Tietysti dos-vinkit eivät enää ehkä niin ajankohtaisia ole, mutta onhan tässäkin monia ainakin aloittelijoille kivoja asioita. Tietysti nuo peräkkäiset saman aliohjelman kutsut olisi voinu laittaa looppiin, jolloin koodi olisi ehkä esteettisempi.
Toimiikos toi nyt varmasti oikein? Itse sain tarkistusmerkiksi '8' vaikka oikea olisi ollut 'T'.
Yksi virhe ainakin paljastui jakojäännöslaskusta (komennon jl tilalla oli jng). Toimiiko nyt oikein?
Nyt näyttää toimivan ainakin mun hetulla.