Super nain tant dos
Introduction
Après le reverse de Aladdin dans le dernier post, j'ai voulu jouer avec un autre jeux, Zombies :
Je crois que ce jeu quand j'étais petit je n'ai jamais réussi à le finir en entier, il est super difficile, mais super fun.
Passwords
Comme dans le jeu Aladdin, tous les 5 levels, on nous file un password pour pouvoir continuer là où on s'est arrêté :
Afin de trouver facilement la routine de vérification des passwords, il m'en fallait un valide, comme ca en tracant le code, je la trouverais facilement, je suis donc allé jusqu'au level 5 :
Sayez je suis en mesure de pouvoir loguer et meme voir les password que je rentre au sein du debugger :
Voici la routine commenté :
$82/B018 AD A0 1E LDA $1EA0 [$82:1EA0]
$82/B01B C9 42 43 CMP #$4342 ====\
$82/B01E D0 0D BNE $0D [$B02D] |
$82/B020 AD A2 1E LDA $1EA2 [$82:1EA2] |
$82/B023 C9 44 46 CMP #$4644 | SECRET LEVEL == "BCDF"
$82/B026 D0 05 BNE $05 [$B02D] =====|
$82/B028 9C 7C 1E STZ $1E7C [$82:1E7C] |
$82/B02B 18 CLC |
$82/B02C 6B RTL /*RET*/ |
$82/B02D E2 30 SEP #$30 <====/
$82/B02F AE A0 1E LDX $1EA0 [$82:1EA0] X = *(0x1EA0)
$82/B032 AD A2 1E LDA $1EA2 [$82:1EA2] A = *(0x1EA2)
$82/B035 8D A0 1E STA $1EA0 [$82:1EA0] *(0x1EA0) = A
$82/B038 8E A2 1E STX $1EA2 [$82:1EA2] *(0x1EA2) = X
$82/B03B C2 30 REP #$30
$82/B03D A2 00 00 LDX #$0000 X = 0
$82/B040 A9 05 00 LDA #$0005 A = 5
$82/B043 8D 7C 1E STA $1E7C [$82:1E7C] *(0x1E7C) = A
$82/B046 E2 30 SEP #$30 <======================================\
$82/B048 BC 4B B1 LDY $B14B,x[$82:CC15] Y = *(0xB14B + x) |
$82/B04B B9 78 B1 LDA $B178,y[$82:B17E] A = *(0xB178 + y) |
$82/B04E EB XBA Exchange byte (ex : 4243 -> 43 42) |
$82/B04F BC 4A B1 LDY $B14A,x[$82:CC14] Y = *(0xB14A + x) |
$82/B052 B9 78 B1 LDA $B178,y[$82:B17E] A = *(0xB178 + y) |
$82/B055 C2 30 REP #$30 |
$82/B057 CD A0 1E CMP $1EA0 [$82:1EA0] |
$82/B05A F0 1B BEQ $1B [$B077] === First stage Ok =====\ |
$82/B05C EE 7C 1E INC $1E7C [$82:1E7C] \ | |
$82/B05F EE 7C 1E INC $1E7C [$82:1E7C] | | |
$82/B062 EE 7C 1E INC $1E7C [$82:1E7C] |--> 0x1E7C += 4 | |
$82/B065 EE 7C 1E INC $1E7C [$82:1E7C] / | |
$82/B068 E8 INX X++; | |
$82/B069 E8 INX X++; | |
$82/B06A E0 1A 00 CPX #$001A if (A == 0x1A) | |
$82/B06D D0 D7 BNE $D7 [$B046] ========================|===============/
$82/B06F A9 01 00 LDA #$0001 |
$82/B072 8D 7C 1E STA $1E7C [$82:1E7C] |
$82/B075 38 SEC |
$82/B076 6B RTL /* RET == Failed */ |
$82/B077 8E 38 00 STX $0038 [$82:0038] <=======================|
$82/B07A A2 00 00 LDX #$0000 X = 0
$82/B07D A9 01 00 LDA #$0001 A = 1
$82/B080 8D 3A 00 STA $003A [$82:003A] *(0x3A) = A
$82/B083 E2 30 SEP #$30 <======================================\
$82/B085 AC 38 00 LDY $0038 [$82:0038] Y = *(0x38) |
$82/B088 BD 65 B1 LDA $B165,x[$82:CC2F] A = *(0xB165 + x) |
$82/B08B 18 CLC |
$82/B08C 79 8E B1 ADC $B18E,y[$82:B194] A += *(0xB18E + y) & 0xff |
$82/B08F A8 TAY Y = A |
$82/B090 B9 78 B1 LDA $B178,y[$82:B17E] A = *(0xB178 + y) |
$82/B093 EB XBA Exchange byte (ex : 4243 -> 43 42) |
$82/B094 AC 38 00 LDY $0038 [$82:0038] Y = *(0x38) |
$82/B097 BD 64 B1 LDA $B164,x[$82:CC2E] A = *(0xB164 + x) |
$82/B09A 18 CLC |
$82/B09B 79 8D B1 ADC $B18D,y[$82:B193] A += *(0xB18D + y) & 0xff |
$82/B09E A8 TAY Y = A |
$82/B09F B9 78 B1 LDA $B178,y[$82:B17E] A = *(0xB17E + y) |
$82/B0A2 C2 30 REP #$30 |
$82/B0A4 CD A2 1E CMP $1EA2 [$82:1EA2] |
$82/B0A7 F0 12 BEQ $12 [$B0BB] === JUMP GOOD BOY === |
$82/B0A9 EE 3A 00 INC $003A [$80:003A] |
$82/B0AC E8 INX x++ |
$82/B0AD E8 INX x++ |
$82/B0AE E0 14 00 CPX #$0014 if (x != 0x14) |
$82/B0B1 D0 D0 BNE $D0 [$B083] =======================================/
$82/B0B3 A9 01 00 LDA #$0001
$82/B0B6 8D 7C 1E STA $1E7C [$80:1E7C]
$82/B0B9 38 SEC
$82/B0BA 6B RTL /* RET = Failed Password */
Elle peut paraitre un peu longue mais en fait il y a une subtilité marrante, pour chaque password, il y en a 10 de possible, chacun d'eux donnera un nombre de victimes différents lorsque vous partirez du niveau désiré.
J'ai ecrit un petit code en python pour les générer:
stage = "HNCVWBXKGZTDLFPSRYJMQ" B14A_offset = [0x10, 0x00, 0x08, 0x05, 0x02, 0x0D, 0x11, 0x07, 0x05, 0x06, 0x0C, 0x11, 0x09, 0x0C, 0x14, 0x12, 0x03, 0x09, 0x0E, 0x10, 0x00, 0x0C, 0x12, 0x04, 0x0F, 0x0B, 0x04, 0x07] B18D_offset = [0x00, 0xFE, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x02, 0xFF, 0xFE, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x01, 0x18, 0x69, 0x8F] B164_offset = [0x04, 0x07, 0x0F, 0x0A, 0x0C, 0x12, 0x10, 0x09, 0x0E, 0x10, 0x03, 0x05, 0x0D, 0x08, 0x08, 0x0C, 0x0A, 0x0E, 0x06, 0x11] x = 0 y = 0 print "Nb victims \t 1\t 2\t 3\t 4\t 5\t 6\t 7\t 8\t 9\t 10" while (x < 0x1a): second = stage[B14A_offset[x + 1]] third = stage[B14A_offset[x]] y = 0 lvl = "Lvl X\t\t" while (y < 0x14): a = B164_offset[y + 1] a += B18D_offset[x + 1] a &= 0xff fourth = stage[a] a = B164_offset[y] a += B18D_offset[x] a &= 0xff first = stage[a] lvl += first + second + third + fourth + "\t" y += 2 print lvl x += 2 print "Secret Level : BCDF"
Voici l'output :
Nb victims 1 2 3 4 5 6 7 8 9 10
Lvl X WHRB SHRG LHRR RHRK PHRP VHRV FHRX GHRT THRL XHRS
Lvl X CBGX FBGZ TBGY PBGG LBGS NBGW DBGK XBGD GBGF WBGR
Lvl X XFCK YFCT PFCJ JFCZ RFCR BFCB SFCG TFCL LFCP GFCY
Lvl X BKYZ RKYL FKYQ YKYD SKYJ WKYK PKYT ZKYP DKYR KKYM
Lvl X VXBB PXBG DXBR SXBK FXBP CXBV LXBX KXBT ZXBL BXBS
Lvl X XYLZ YYLL PYLQ JYLD RYLJ BYLK SYLT TYLP LYLR GYLM
Lvl X XLZG YLZD PLZM JLZT RLZY BLZX SLZZ TLZF LLZS GLZJ
Lvl X WJQK SJQT LJQJ RJQZ PJQR VJQB FJQG GJQL TJQP XJQY
Lvl X BZVG RZVD FZVM YZVT SZVY WZVX PZVZ ZZVF DZVS KZVJ
Lvl X BRPK RRPT FRPJ YRPZ SRPR WRPB PRPG ZRPL DRPP KRPY
Lvl X VLHX PLHZ DLHY SLHG FLHS CLHW LLHK KLHD ZLHF BLHR
Lvl X WWJX SWJZ LWJY RWJG PWJS VWJW FWJK GWJD TWJF XWJR
Lvl X WDSG SDSD LDSM RDST PDSY VDSX FDSZ GDSF TDSS XDSJ
Secret Level : BCDF
On teste le secret level and it works :
Tous les autres passwords sont aussi fonctionnels, Have fun :]