[EA][ASM][Tool] lyn (elf2ea if you will)

Second release of lyn (well third because I fucked up n°2 but shh)

  • Removed dependency on the Hack Installation EA extention (BL -> a bunch of SHORTs)
  • Added program options (see below)
  • Allowed processing multiple elves (lol) together, and anticipate linking when applicable
  • Allowed forcing external BL calls to be converted to absolute calls through “trampolines” (“veneers” as the official ARM ELF spec calls them)
  • Allowed automatic hooking into vanilla routines (if both an absolute & a local symbol of the same name exist, and said absolute symbol points to ROM, then lyn will automatically output a hook the local symbol wherever the original absolute symbol pointed to)

Usage (new):

lyn [-nolink/-linkabs/-linkall] [-longcalls] [-raw] [-printtemp] [-autohook] <elf...>
  • -nolink/-linkabs/-linkall defines linking policy. Behavior may conflict when other options are set (other options usually have priority).
    • -nolink prevents any anticipated linking to occur (all relocations will be exposed to EA)
    • -linkabs will only link absolute symbols (ie symbols that cannot simply be represented as labels using EA)
    • -linkall will link everything it can (absolutes, relatives, locals…) (set by default)
  • -longcalls will transform any direct BL call (and maybe later other calls/jumps) to a call to a “trampoline”, where the target symbol will be represented as absolute.
  • -raw will prevent any anticipated computation to occur, exposing the elves as is.
  • -printtemp will expose temporary symbols (for now this only includes labels associated with trampolines)
  • -autohook will allow automatic hooking into vanilla routines (see above for details). On by default (disable it with -raw)

Also since it has been brought to my attention that my examples actually didn’t show what lyn actually does, here’s a brief extra of the OP walk-through:

EXTRA: What lyn does

Let’s assume the following source:

Same ASM as before more or less
.thumb

.global GetStatIncrease
.type   GetStatIncrease, %function

@ Arguments: r0 = Growth
@ Returns: r0 = Stat Increase
GetStatIncrease:
	push {r4-r5, lr}
	
	mov r4, r0
	mov r5, #0
	
Continue:
	ldr r3, =NextRN_100
	mov lr, r3
	.short 0xF800
	
	sub r4, r0 @ r4 = (r4 - RN100)
	blt End    @ if (r4 < 0) goto End;
	
	add r5, #1 @ stat++
	
	b Continue
	
End:
	mov r0, r5
	
	pop {r4-r5}
	
	pop {r1}
	bx r1

Let it go through lyn and you get this:

lyn output
PUSH
ORG (CURRENTOFFSET+$1); GetStatIncrease:
POP

SHORT $B530 $1C04 $2500 $4B05 $469E
BYTE $00 $F8
SHORT $1A24 $DB01 $3501 $E7F8 $1C28 $BC30 $BC02 $4708
POIN NextRN_100

syntax highlighting colors didn’t explode for once lol

So what happened here is that

  • assembled asm got inserted using SHORTs (thumb opcodes are 2 bytes, so it used SHORTs because why not) (the one BYTE $00 $F8 part is because of the .short 0xF800, which is the second part of the bl opcode)
  • the one global symbol in our asm got exposed (GetStatIncrease) as a label (the +$1 is because of the thumb bit. tl;dr if you expose a symbol that “points” to thumb code, then that symbol will automatically gain the thumb bit)
  • the one reference to an external symbol (aka relocation) got exposed (POIN NextRN_100)

Ok so that’s what lyn does, and it was all it did until today’s update.

Going further with lyn

With today’s shiny new features, we can basically write a simple hack that replaces a vanilla routine using only a lyn call!

Ok so first, here’s another file, that we are going to call the “definitions” file:

Definitions.s

.macro SET_FUNC name, value
	.global \name
	.type   \name, %function
	.set    \name, \value
.endm

SET_FUNC NextRN_100,      (0x08000C64+1)
SET_FUNC GetStatIncrease, (0x0802B9A0+1)

It’s basically defining the offsets of some vanilla routines, with the thumb bit (the thumb bit is kinda important).
What the elf version of this file does is expose those values as absolute symbols, which won’t be exposed to EA, but will be very useful when it comes to anticipated linking.

So how about we call lyn one last time so I can prove my point (make sure to have assembled your source files to elves!)

lyn "GetStatIncrease.elf" "Definitions.elf"
This is what we get
PUSH
ORG $2b9a0
SHORT $4778 $46C0
WORD $E59FC000 $E12FFF1C
POIN GetStatIncrease
POP
PUSH
ORG (CURRENTOFFSET+$1); GetStatIncrease:
POP

SHORT $B530 $1C04 $2500 $4B05 $469E
BYTE $00 $F8
SHORT $1A24 $DB01 $3501 $E7F8 $1C28 $BC30 $BC02 $4708
BYTE $65 $0C $00 $08

Ok so first big difference from what we had before is there’s a bunch of new stuff at the start of the output. A PUSH, an ORG to a fixed location… You guessed it: it’s a hook into a vanilla routine. This is what the new automatic hooking feature allows us to do. Here’s an asm version of whatever that is:

common lyn trampoline
.thumb
bx pc @ switch to ARM
nop @ .align
.arm
ldr r12, =GetStatIncrease @ load target in r12 (ip)
bx r12 @ goto r12 (ip)
.word GetStatIncrease

Note: this piece of ASM is according to the ARM ELF spec a valid “ip-corrupting veneer”, which is the kind of extra piece of code a linker is allowed to insert to allow for long jumps & arm/thumb switches between different object files

I said common lyn trampoline since it’s the same that is used when the -longcalls option is specified.

Anyway what this does is hook into a vanilla call and redirect to our own GetStatIncrease routine. In effect it replaces the routine.

Other than that, not much different from before… except maybe for the fact that the NextRN_100 reference is… gone! Well that would make sense since we specified it’s value in our Definitions elf and when you look closed, you’ll find a BYTE $65 $0C $00 $08 part in the EA output… yes there it is! It may not seem like much but it allows us to bypass having to define the value of it in both EA & our original source… Which is especially useful in case you’re working with a elf-generator that doesn’t allow for defining any value for any symbol.

With all of this, it reduces our event file to do the following:

Final events

{
	ALIGN 4
	#inctext lyn "asm/GetStatIncrease.elf" "asm/Definitions.elf"
}

…Oh. All our hack installer has become is a call to lyn… Well that’s mission accomplished! We made a small hook hack using only a lyn call!

Phew. Now that’s done, let me tell you a thing: I’m probably done with adding major features to lyn at this point. Any further update will probably be small additions & fixes. I do plan on working on one or more tools to go with the lyn-based hacking workflow, and after that maybe coming back to tea, and after that I may do some actual hacking (lol).

Have another great day! - StanH_

6 Likes