BkP CTF 2013 | space game [Write-Up]

Un binaire nous était donné, mais celui était un peu spécial : space_game.nds était un fichier de jeu Nintendo DS !
On va utiliser un émulateur NDS, comme DeSmuME. On load le fichier, et on est face à ceci…

image1

Mmhh, apparemment il faut envoyer une certaine combinaison de keycodes (appuis sur boutons).
On essaye, un peu au hasard, des touches (qui correspondent, dans la configuration des touches de l’émulateur, à des boutons de la console) et au bout de plusieurs touches, on nous dit…

image2

Bon. Arrêtons de faire n’importe quoi. Nous avons utilisé un loader IDA qui permet de désassembler les jeux NDS.
On regarde les strings intéressantes : « Enter the correct keycodes for the flag » par exemple, utilisée dans la fonction sub_20169D4.


RAM:02016B58 loc_2016B58 ; CODE XREF: sub_20169D4+A4j
RAM:02016B58 ; sub_20169D4+166j
RAM:02016B58 BL sub_2000FAC
RAM:02016B5C MOV R0, R11
RAM:02016B5E BL sub_200A76C
RAM:02016B62 LDR R0, =aEnterTheCorrec ; "Enter the correct key codes for the fla"...
RAM:02016B64 BL sub_200A76C
RAM:02016B68 MOV R2, R8
RAM:02016B6A LDR R2, [R2,#4]
RAM:02016B6C CMP R2, #7
RAM:02016B6E BEQ loc_2016B72
RAM:02016B70 B loc_2016A2E
RAM:02016B72 ; ---------------------------------------------------------------------------
RAM:02016B72
RAM:02016B72 loc_2016B72 ; CODE XREF: sub_20169D4+19Aj
RAM:02016B72 BL sub_2000430
RAM:02016B76 MOV R3, R8
RAM:02016B78 STR R0, [R3,#8]
RAM:02016B7A CMP R0, #1
RAM:02016B7C BEQ loc_2016B86
RAM:02016B7E LDR R0, =aNiceTry___YouR ; "nice try... you're wrong though *<:-)"
RAM:02016B80 BL sub_200A76C
RAM:02016B84 B loc_2016A2E
RAM:02016B86 ; ---------------------------------------------------------------------------
RAM:02016B86
RAM:02016B86 loc_2016B86 ; CODE XREF: sub_20169D4+1A8j
RAM:02016B86 BL sub_20003EC
RAM:02016B8A MOV R2, R10
RAM:02016B8C LDR R1, [R2]
RAM:02016B8E ADD R0, SP, #0x90+var_8C
RAM:02016B90 MOVS R2, #0x10
RAM:02016B92 BL sub_2000310
RAM:02016B96 ADD R0, SP, #0x90+var_8C
RAM:02016B98 BL sub_200046C
RAM:02016B9C MOV R3, SP
RAM:02016B9E STRB R6, [R0,#0xB]
RAM:02016BA0 MOVS R1, R0
RAM:02016BA2 LDR R0, =aKeyS ; "key{%s}\n"
RAM:02016BA4 STRB R6, [R3,#0x90+var_81]
RAM:02016BA6 BL sub_200A618
RAM:02016BAA B loc_2016A2E
RAM:02016BAA ; End of function sub_20169D4
RAM:02016BAA
RAM:02016BAA ; ---------------------------------------------------------------------------

Ah oui, nous avons oublié de le préciser. Les NDS utilisent une architecture ARM !
Une fois les touches (keycodes) tapées, un appel à une fonction sub_2000430 est faite. Si cette fonction renvoie 1, alors on passe à la routine en 0x02016B86 qui va se charger de déchiffrer le flag key{xxx}.
Regardons donc cette fonction sub_2000430 :


RAM:02000430 sub_2000430 ; CODE XREF: sub_20169D4:loc_2016B72p
RAM:02000430 PUSH {LR}
RAM:02000432 LDR R3, =dword_2021464
RAM:02000434 MOVS R0, #0
RAM:02000436 LDR R3, [R3]
RAM:02000438 LDRB R2, [R3,#5]
RAM:0200043A CMP R2, #0x47
RAM:0200043C BEQ loc_2000440
RAM:0200043E
RAM:0200043E locret_200043E ; CODE XREF: sub_2000430+14j
RAM:0200043E ; sub_2000430+1Aj ...
RAM:0200043E POP {PC}
RAM:02000440 ; ---------------------------------------------------------------------------
RAM:02000440
RAM:02000440 loc_2000440 ; CODE XREF: sub_2000430+Cj
RAM:02000440 LDRB R2, [R3,#2]
RAM:02000442 CMP R2, #0x56
RAM:02000444 BNE locret_200043E
RAM:02000446 LDRB R2, [R3,#1]
RAM:02000448 CMP R2, #0x6E
RAM:0200044A BNE locret_200043E
RAM:0200044C LDRB R2, [R3,#3]
RAM:0200044E CMP R2, #0x73
RAM:02000450 BNE locret_200043E
RAM:02000452 LDRB R2, [R3]
RAM:02000454 CMP R2, #0x5A
RAM:02000456 BNE locret_200043E
RAM:02000458 LDRB R2, [R3,#6]
RAM:0200045A CMP R2, #0x46
RAM:0200045C BNE locret_200043E
RAM:0200045E LDRB R0, [R3,#4]
RAM:02000460 SUBS R0, #0x62
RAM:02000462 NEGS R3, R0
RAM:02000464 ADCS R0, R3
RAM:02000466 B locret_200043E
RAM:02000466 ; End of function sub_2000430

Plusieurs comparaisons sont faites avec une certaine chaîne de caractères qui semble être fonction des touches tapées…
Elle est comparée, octet par octet, à plusieurs valeurs : 56, 6E, 73, 5A…
Nous n’avons pas cherché à comprendre plus loin. Revenons en arrière. Voici la comparaison utilisée :


RAM:02016B72 BL sub_2000430
RAM:02016B76 MOV R3, R8
RAM:02016B78 STR R0, [R3,#8]
RAM:02016B7A CMP R0, #1
RAM:02016B7C BEQ loc_2016B86

R0 devrait être le retour de notre fonction, il est comparé à 1. D’après IDA, le CMP se trouve à l’adresse réelle 0x16D7A.
Prenons un éditeur hexadécimal et allons voir à cette adresse. On peut voir un 0x01, qui doit correspondre à la valeur à laquelle est comparée le registre R0.
Modifions ce 0x01 par un 0x00. Normalement, le programme devrait maintenant afficher le flag lorsque la combinaison rentrée est fausse.
Lançons-le avec l’émulateur :

image3

Woot! Avec un peu de guessing, on peut reconstituer le flag : thegamesux.
Sur les 10 caractères du mot de passe, seul les 3 premiers on été faux. Nous avons eu de la chance, pour une combinaison au hasard (en imaginant que le flag affiché est fonction de la combinaison rentrée).

Enjoy 🙂

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s