Saturday, February 9, 2013

Decompilation example

Quick example of how well the plugin works



void RestoreHealth(){ //Original function
u16* curHealth=(u16*)0x3001310;
u16* maxHealth=(u16*)0x3001312;
unsigned short val=*maxHealth-*curHealth;
*curHealth+=val;

}


Here's the assembeled copy
            EXPORT RestoreHealth
RestoreHealth

var_8           = -8
var_4           = -4

                SUB     SP, SP, #0x10
                LDR     R3, =0x3001310
                STR     R3, [SP,#0x10+var_4]
                LDR     R3, =0x3001312
                STR     R3, [SP,#0x10+var_8]
                LDR     R3, [SP,#0x10+var_8]
                LDRH    R1, [R3]
                LDR     R3, [SP,#0x10+var_4]
                LDRH    R2, [R3]
                MOV     R3, SP
                ADDS    R3, #6
                SUBS    R2, R1, R2
                STRH    R2, [R3]
                LDR     R3, [SP,#0x10+var_4]
                LDRH    R2, [R3]
                MOV     R3, SP
                ADDS    R3, #6
                LDRH    R3, [R3]
                ADDS    R3, R2, R3
                LSLS    R3, R3, #0x10
                LSRS    R2, R3, #0x10
                LDR     R3, [SP,#0x10+var_4]
                STRH    R2, [R3]
                ADD     SP, SP, #0x10
                BX      LR
; End of function RestoreHealth

; ---------------------------------------------------------------------------
                ALIGN 0x10
dword_8000320   DCD 0x3001310           ; DATA XREF: RestoreHealth+2 r
dword_8000324   DCD 0x3001312           ; DATA XREF: RestoreHealth+6 r

And here's the decompiled version! 


; ---------------------------------------------------------------------------

                EXPORT RestoreHealth
RestoreHealth
                void RestoreHealth() { // framesize 0x10

                 (unsigned long)SP+0xC = 0x3001310;
                 (unsigned long)SP+8 = 0x3001312;
                 (unsigned short)SP+6 = word<(unsigned long)SP+8> - word<(unsigned long)SP+0xC>;
                 word<(unsigned long)SP+0xC> = word<(unsigned long)SP+0xC> + (unsigned short)SP+6 & 0xFFFF;
                 return void
                }
; ---------------------------------------------------------------------------

Decompiler update

Greetings!


There is now a repository for the decompiler!
http://code.google.com/p/arm-thumb-decompiler-plugin/
If you wish to be a committer please e-mail myself or normmatt.

Helpers are welcome! :)


Here's the current r11 binaries.

https://dl.dropbox.com/u/12510094/NEVERDELETE/decompilerr11.zip


Romhacking update soon, maybe today.

Best jump table detection!


Monday, February 4, 2013

Fixed a bug in the decompiler

Hello!

Last release of the decompiler could only detect switches in the following format.

80 00   LSL   R0, R0, #2

02 49   LDR   R1, =off_83C173C
40 18   ADD   R0, R0, R1
00 68   LDR   R0, [R0]
87 46   MOV   PC, R0

I successfully have it reading switches from r1, and will be advancing it to switches with any registers.

I also have to look into getting default case switches to work.

Expect a release soon!

Sunday, February 3, 2013

Thumb Decompiler plugin

Hello!

Here's the first release of that decompiler I've been talking about. It's a huge help, thank you Ludde.


Updates will come and I'll eventually get a googlecode for it.


Little tutorial on setup


Hello! This is a quick tutorial on how to use the updated version of Luddes, thumdecompiler.

Easy to use, with powerful results. That man is a genius. Anyway, it's helped me a lot and I hope it can help with malicious, or bad code or debug something that got compiled wrong

https://dl.dropbox.com/u/12510094/NEVERDELETE/IDATHUMBDECOMPILER.zip Plug in link

https://dl.dropbox.com/u/12510094/NEVERDELETE/thumb.zip Source code.
So....There are a ton of event check functions.

A lot are repeated, I believe the ones I labelled 2 are to check for the event to have occurred  and ones without two are to check if the event is the current event or not

Anyway,


;



EVENT_AfterAuxEventSET:                 ; 0x801C0E8+2
                int EVENT_AfterAuxEventSET() {

                 R1 = (EventCounter != 0x4B ? 0 : 1)
                 return R1
                }
; End of function EVENT_AfterAuxEventSET


;



EVENT_EngagedSaXSET:                    ; 0x801C0E8:loc_801C120
                int EVENT_EngagedSaXSET() {

                 R1 = (EventCounter != 0x4C ? 0 : 1)
                 return R1
                }
; End of function EVENT_EngagedSaXSET


;



EVENT_IceBeamSET:                       ; 0x8010220+730
                                        ; sub_8010220+7C2 ...
                int EVENT_IceBeamSET() {

                 R1 = (EventCounter <=u 0x6A ? 0 : 1)
                 return R1
                }
; End of function EVENT_IceBeamSET


;



EVENT_FinalTripToHangerSET:             ; 0x8054978+A
                                        ; sub_8054A3C+2A ...
                int EVENT_FinalTripToHangerSET() {

                 R1 = (EventCounter <=u 0x69 ? 0 : 1)
                 return R1
                }
; End of function EVENT_FinalTripToHangerSET


;



EVENT_FinalSAXFightSET:                 ; 0x801A914+2
                int EVENT_FinalSAXFightSET() {

                 R1 = (EventCounter != 0x65 ? 0 : 1)
                 return R1
                }
; End of function EVENT_FinalSAXFightSET


;



EVENT_BoxQuakeSET:                      ; CODE XREF: Enemy9F_AI+1B0
                int EVENT_BoxQuakeSET() {

                 R1 = (EventCounter != 0x5A ? 0 : 1)
                 return R1
                }
; End of function EVENT_BoxQuakeSET


;



EVENT_RestricttedLabBlockedSET:         ; CODE XREF: Enemy9F_AI:loc_8030358
                int EVENT_RestricttedLabBlockedSET() {

                 R1 = (EventCounter != 0x59 ? 0 : 1)
                 return R1
                }
; End of function EVENT_RestricttedLabBlockedSET


;



EVENT_HasVariaSET:                      ; 0x80412F0+2C
                int EVENT_HasVariaSET() {

                 R1 = (EventCounter <=u 0x33 ? 0 : 1)
                 return R1
                }
; End of function EVENT_HasVariaSET


;



EVENT_IsPowerOutSET:                    ; 0x8056DF4+4A
                int EVENT_IsPowerOutSET() {

                 R1 = EventCounter
                 R0 = 1
                 if (R1 == 0x46)
                    return R0

                 R0 = 0
                 if (R1 <=u 0x46)
                    return R0

                 return 2
                }
; End of function EVENT_IsPowerOutSET


;



EVENT_HasWaveBeamSET:                   ; CODE XREF: Enemy9F_AI:loc_8030340
                int EVENT_HasWaveBeamSET() {

                 R1 = (EventCounter != 0x5B ? 0 : 1)
                 return R1
                }
; End of function EVENT_HasWaveBeamSET


;



EVENT_ReachedDeadEndRestrictedSET:      ; CODE XREF: Enemy9F_AI:loc_803034C
                                        ; Enemy9F_AI+1DC ...
                int EVENT_ReachedDeadEndRestrictedSET() {

                 R1 = (EventCounter != 0x5C ? 0 : 1)
                 return R1
                }
; End of function EVENT_ReachedDeadEndRestrictedSET


;



EVENT_AfterBombsSET:                    ; CODE XREF: Enemy9F_AI+184
                int EVENT_AfterBombsSET() {

                 R1 = (EventCounter != 0x17 ? 0 : 1)
                 return R1
                }
; End of function EVENT_AfterBombsSET


;



sub_8060C78:                            ; CODE XREF: Enemy9F_AI:loc_8030334
                int sub_8060C78() {

                 R1 = (EventCounter != 0x16 ? 0 : 1)
                 return R1
                }
; End of function sub_8060C78


;



EVENT_EscSaxBeforVariaSET:              ; 0x804378C+E0
                int EVENT_EscSaxBeforVariaSET() {

                 R1 = (EventCounter != 0x31 ? 0 : 1)
                 return R1
                }
; End of function EVENT_EscSaxBeforVariaSET


;



EVENT_SAXEntersPostPBSET:               ; 0x80193C4:loc_8019428
                                        ; sub_8019520+4
                int EVENT_SAXEntersPostPBSET() {

                 R1 = (EventCounter != 0x43 ? 0 : 1)
                 return R1
                }
; End of function EVENT_SAXEntersPostPBSET


;



sub_8060CC0:                            ; 0x80193C4+3C
                int sub_8060CC0() {

                 R1 = (EventCounter != 0x42 ? 0 : 1)
                 return R1
                }
; End of function sub_8060CC0


;



EVENT_SAXEntersPreVariaSET:             ; CODE XREF: PowerBombSaxInit+F
                                        ; BeginSAXRoutine+2
                int EVENT_SAXEntersPreVariaSET() {

                 R1 = (EventCounter != 0x30 ? 0 : 1)
                 return R1
                }
; End of function EVENT_SAXEntersPreVariaSET


;



EVENT_GoGetVariaSET:                    ; CODE XREF: PowerBombSaxInit+8
                int EVENT_GoGetVariaSET() {

                 R1 = (EventCounter != 0x2F ? 0 : 1)
                 return R1
                }
; End of function EVENT_GoGetVariaSET


;



EVENT_GotHighJumpSET:                   ; CODE XREF: SomeSaxRoutine+2
                int EVENT_GotHighJumpSET() {

                 R1 = (EventCounter != 0x19 ? 0 : 1)
                 return R1
                }
; End of function EVENT_GotHighJumpSET


;



EVENT_GotHighJump2SET:                  ; 0x80429B8+2
                                        ; Enemy89_AI:loc_8042B7A
                int EVENT_GotHighJump2SET() {

                 R1 = (EventCounter <=u 0x19 ? 0 : 1)
                 return R1
                }
; End of function EVENT_GotHighJump2SET


;



EVENT_TriggeredBOXSET:                  ; 0x8037E18+6E
                                        ; sub_803808C+242 ...
                int EVENT_TriggeredBOXSET() {

                 R1 = (EventCounter <=u 0x27 ? 0 : 1)
                 return R1
                }
; End of function EVENT_TriggeredBOXSET


;



EVENT_TriggeredBOX2SET:                 ; CODE XREF: Enemy20_AI:loc_803061A
                                        ; sub_8035C58+4
                int EVENT_TriggeredBOX2SET() {

                 R1 = (EventCounter != 0x27 ? 0 : 1)
                 return R1
                }
; End of function EVENT_TriggeredBOX2SET


;



EVENT_HaveSuperMissilesSET:             ; CODE XREF: Enemy9F_AI+14C
                                        ; Enemy20_AI:loc_803059E
                int EVENT_HaveSuperMissilesSET() {

                 R1 = (EventCounter != 0x26 ? 0 : 1)
                 return R1
                }
; End of function EVENT_HaveSuperMissilesSET


;



EVENT_IsInSuperMissileRoomSET:          ; CODE XREF: Enemy9F_AI:loc_8030328
                int EVENT_IsInSuperMissileRoomSET() {

                 R1 = (EventCounter != 0x25 ? 0 : 1)
                 return R1
                }
; End of function EVENT_IsInSuperMissileRoomSET


;



EVENT_EnteredPumpControlSET:            ; 0x8030E14:loc_8030E96
                int EVENT_EnteredPumpControlSET() {

                 R1 = (EventCounter <=u 0x1F ? 0 : 1)
                 return R1
                }
; End of function EVENT_EnteredPumpControlSET


;



EVENT_OnToQuarantineBaySET:             ; 0x801CA1C+A
                int EVENT_OnToQuarantineBaySET() {

                 R1 = (EventCounter != 1 ? 0 : 1)
                 return R1
                }
; End of function EVENT_OnToQuarantineBaySET


;



EVENT_GenericSet:                       ; 0x801F2C0+36
                int EVENT_GenericSet() {

                 R2 = 0
                 R1 = EventCounter
                 if ((R1 - 0x3B & 0xFF) <=u 1 || (R1 - 0x46 & 0xFF) <=u 3 || R1 >u 0x66)
                    R2 = 1

                 return R2
                }
; End of function EVENT_GenericSet


;



EVENT_Generic2Set:                      ; 0x802A11C+5C
                int EVENT_Generic2Set() {

                 R2 = 0
                 R1 = EventCounter
                 if ((R1 - 0x46 & 0xFF) <=u 3 || R1 >u 0x66)
                    R2 = 1

                 return R2
                }
; End of function EVENT_Generic2Set


;



EVENT_Generic3Set:                      ; 0x802BEC4+42
                int EVENT_Generic3Set() {

                 R1 = ((EventCounter - 0x46 & 0xFF) >u 3 ? 0 : 1)
                 return R1
                }
; End of function EVENT_Generic3Set

                .align 4
                .long EventCounter

;



EVENT_EnteredPumpControl2SET:           ; 0x8039248:loc_80392AE
                int EVENT_EnteredPumpControl2SET() {

                 R1 = (EventCounter != 0x1F ? 0 : 1)
                 return R1
                }
; End of function EVENT_EnteredPumpControl2SET


;



EVENT_WideBeamGETorMeltdownSET:         ; 0x8039248:loc_80392B4
                                        ; sub_8039680+A ...
                int EVENT_WideBeamGETorMeltdownSET() {

                 R1 = 0
                 R0 = EventCounter
                 if (R0 == 0x3B) {
                    R1 = 1
                    return R1
                 }

                 if (R0 == 0x3C)
                    R1 = 2

                 return R1
                }
; End of function EVENT_WideBeamGETorMeltdownSET


;



EVENT_TharBeWildLifeSET:                ; 0x8039248:loc_80392E6
                int EVENT_TharBeWildLifeSET() {

                 R1 = (EventCounter != 0x3E ? 0 : 1)
                 return R1
                }
; End of function EVENT_TharBeWildLifeSET


;



EVENT_TharBeWildLife2SET:               ; 0x8030868+BE
                                        ; sub_80309A0:loc_80309B2 ...
                int EVENT_TharBeWildLife2SET() {

                 R1 = (EventCounter <=u 0x3E ? 0 : 1)
                 return R1
                }
; End of function EVENT_TharBeWildLife2SET


;



EVENT_HasSpaceJump:                     ; 0x8039248:loc_80392DC
                int EVENT_HasSpaceJump() {

                 R1 = (EventCounter != 0x49 ? 0 : 1)
                 return R1
                }
; End of function EVENT_HasSpaceJump


;



EVENT_SAXSaviorEscapesSET:              ; 0x80399B0+64
                int EVENT_SAXSaviorEscapesSET() {

                 R1 = (EventCounter != 0x66 ? 0 : 1)
                 return R1
                }
; End of function EVENT_SAXSaviorEscapesSET


;



EVENT_SAXSaviorEscapes2SET:             ; 0x80399B0:loc_8039A40
                int EVENT_SAXSaviorEscapes2SET() {

                 R1 = (EventCounter <=u 0x66 ? 0 : 1)
                 return R1
                }
;EVENT_SAXSaviorEscapes2SET


;


GetWhichTimer:                          ; 0x802A310+2
                                        ; sub_804F614+2 ...
                int GetWhichTimer() {

                 R2 = 0
                 R0 = EventCounter - 0x3B
                 if (R0 >u 0x31)
                    return R2

                 if (R0 == 0 || R0 == 1) {
                    R2 = 1
                    return R2
                 }

                 if (R0 == 2 || R0 == 3 || R0 == 4 || R0 == 5 || R0 == 6 || R0 == 7 || R0 == 8 || R0 == 9 || R0 == 0xA || R0 == 0xB || R0 == 0xC || R0 == 0xD || R0 == 0xE || R0 == 0xF || R0 == 0x10 || R0 == 0x11 || R0 == 0x12 || R0 == 0x13 || R0 == 0x14 || R0 == 0x15 || R0 == 0x16 || R0 == 0x17 || R0 == 0x18 || R0 == 0x19 || R0 == 0x1A || R0 == 0x1B || R0 == 0x1C || R0 == 0x1D || R0 == 0x1E || R0
                    return R2

                 if (R0 == 0x22) {
                    R2 = 2
                    return R2
                 }

                 if (R0 == 0x23 || R0 == 0x24 || R0 == 0x25 || R0 == 0x26 || R0 == 0x27 || R0 == 0x28 || R0 == 0x29 || R0 == 0x2A || R0 == 0x2B)
                    return R2

                 if (R0 != 0x2C && R0 != 0x2D && R0 != 0x2E && R0 != 0x2F && R0 == 0x30) {
                 }

                 R2 = 3
                 return R2
                }
;GetWhichTimer


;



EVENT_CheckMajorEventsSET:              ; 0x80746CC+64 p
                int EVENT_CheckMajorEventsSET() {

                 R1 = 0
                 R0 = EventCounter
                 if (R0 == 0x3D || R0 == 0x5E || R0 == 0x6D)
                    R1 = 1

                 return R1
                }
;EVENT_CheckMajorEventsSET

ASM post coming soon!

Sunday or Monday, the next tutorial will be up!

We will again be hacking Metroid Fusion.
Our goal this time, will be to completely fill up our energy whenever we pass through a door.

I will be issuing homework I hope some will try it!

We will be learning how to track down our target addresses.
Learn how to Hi-Jack addresses
And how to return :D

I'm not the best, but it works well and that's how I'm teaching!