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,21Oho. 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.