From 61ea7d2f10f9791aa3fe2fc6304563ea08467472 Mon Sep 17 00:00:00 2001 From: nucular Date: Thu, 7 Jun 2018 14:56:55 +0200 Subject: [PATCH] Started reverse-engineering --- .gitignore | 4 + README.md | 52 +++++++++++- is_licensed.asm | 215 ++++++++++++++++++++++++++++++++++++++++++++++++ sub_EC96290.asm | 209 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 is_licensed.asm create mode 100644 sub_EC96290.asm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7106844 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.elf +*.id? +*.nam +*.til diff --git a/README.md b/README.md index 95f1f4f..93ade5e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ MPEG-2 and VP1 hardware video encoding. ## Patch -A bootloader patch that disables licensing checks was posted to +A patch for `start.elf`, a firmwware blob for the VideoCore IV processor used by +all Raspberry Pi models, was posted to [reddit](https://www.reddit.com/r/raspberry_pi/comments/5x7xbo/patch_for_mpeg2_vc1_license/) by [/u/fuck_the_mpeg_la](https://www.reddit.com/user/fuck_the_mpeg_la) on 03-03-2017: @@ -16,6 +17,23 @@ cp start.elf start.elf_backup && \ perl -pne 's/\x47\xE9362H\x3C\x18/\x47\xE9362H\x3C\x1F/g' < start.elf_backup > start.elf ``` +Applying it to a +[4.14.44 `start.elf`](https://github.com/raspberrypi/firmware/blob/a154f2136850dba827cf4bc40794854376902cbd/boot/start.elf) +(latest as of time of writing) results in the following diff: +```bash +$ diff <(xxd -e start.elf_backup) <(xxd -e start.elf) +38340c38340 +< 00095c30: 400703a4 40161799 3633e947 183c4832 ...@...@G.362H<. +--- +> 00095c30: 400703a4 40161799 3633e947 1f3c4832 ...@...@G.362H<. +``` + +```bash +$ md5sum start.elf_backup start.elf +8327a0720f806814b677efaeb94a7671 start.elf_backup +fe55537c71b22e8f8c1a92257da2c45b start.elf +``` + Some initial analysis was done by [q3k](https://news.ycombinator.com/user?id=q3k) on [Hacker News](https://news.ycombinator.com/item?id=16383368): @@ -24,3 +42,35 @@ on [Hacker News](https://news.ycombinator.com/item?id=16383368): >to always be taken, thus always allowing all codecs. ![Mirrored from https://q3k.org/u/8e3173aef341df726e4f38f30e58417239423250f3e44f5b8b79acdc451d1553.png](assets/patch.png) + +## Reverse-engineering + +The initial entry point is disassembled using the +[VideoCore IV plugin](https://github.com/hermanhermitage/videocoreiv/tree/master/idaplugin) +for IDA Pro 6 by [hermanhermitage](https://github.com/hermanhermitage). + +After loading and analyzing `start.elf`, we can find the `is_licensed` routine +at address `0xEC96290` by jumping to the file offset given to us by `xxd` +beforehand. The relevant code sections are available in +[sub_EC96290.asm](sub_EC96290.asm) and [is_licensed.asm](is_licensed.asm). + +```asm +not_WMV9: ; CODE XREF: is_licensed+56j + cmp r7, 'MPG2' + cmpeq r6, 0 + bne not_MPG2 + ld r1, 0x1DC0(gp) ; XREF 0xEE86680 dword_EE86680 + addcmpbne r1, 0, 0, return_1 + +not_MPG2: ; CODE XREF: is_licensed+68j + cmp r7, 'WVC1' + cmpeq r6, 0 + bne deny + ld r2, 0x2120(gp) ; XREF 0xEE869E0 dword_EE869E0 + addcmpbeq r2, 0, 0, deny +``` + +Here, two memory locations (`0xEE86680` for MPEG-2 and `0xEE869E0` for VP1) +that point to the `.bss` segment are checked to determine the return value of +`is_licensed`. There are no other obvious references to these locations in +`start.elf`, so memory-breakpoint debugging (**TBD**) is probably needed. diff --git a/is_licensed.asm b/is_licensed.asm new file mode 100644 index 0000000..2fa41e6 --- /dev/null +++ b/is_licensed.asm @@ -0,0 +1,215 @@ + + + +; =============== S U B R O U T I N E ======================================= + + +is_licensed: ; CODE XREF: sub_EC64B68+10Ap + ; sub_EC960D4+D8p ... + stm r6-r16, lr, (--sp) + mov r7, r0 + lea sp, 0xFFFFFFF0(sp) + mov r6, r1 + cmp r7, 'H263' + beq return_1 + cmp r7, 'H264' + beq return_1 + cmp r7, 'MVC0' + beq return_1 + cmp r7, 'MPG4' + beq return_1 + cmp r7, 'MJPA' + beq return_1 + cmp r7, 'MJPB' + beq return_1 + cmp r7, 'MJPG' + beq return_1 + cmp r7, 'AGIF' + beq return_1 + cmp r7, 'PCM' + beq return_1 + cmp r7, 'WMV9' + bne not_WMV9 + mov r7, 'WVC1' + +not_WMV9: ; CODE XREF: is_licensed+56j + cmp r7, 'MPG2' + cmpeq r6, 0 + bne not_MPG2 + ld r1, 0x1DC0(gp) ; XREF 0xEE86680 dword_EE86680 + addcmpbne r1, 0, 0, return_1 + +not_MPG2: ; CODE XREF: is_licensed+68j + cmp r7, 'WVC1' + cmpeq r6, 0 + bne deny + ld r2, 0x2120(gp) ; XREF 0xEE869E0 dword_EE869E0 + addcmpbeq r2, 0, 0, deny + +return_1: ; CODE XREF: is_licensed+Ej + ; is_licensed+16j ... + mov r0, 1 + b return +; --------------------------------------------------------------------------- + +deny: ; CODE XREF: is_licensed+7Cj + ; is_licensed+82j + mov r5, r7 + lea r8, 0x4(sp) + and r5, 0xFF000000 + addcmpbeq r5, 0, 0, loc_EC96354 + lea r1, 0x12E(pc) ; "%s_%c%c%c%c" + addcmpbeq r6, 0, 0, loc_EC96338 + lea r2, 0x764(gp) ; XREF 0xEE85024 aEncode ; "encode" + b loc_EC9633C +; --------------------------------------------------------------------------- + +loc_EC96338: ; CODE XREF: is_licensed+9Ej + lea r2, 0x76B(gp) ; XREF 0xEE8502B aDecode ; "decode" + +loc_EC9633C: ; CODE XREF: is_licensed+A6j + lsr r4, r7, 0x10 + lsr r5, r7, 0x8 + bmask r0, r7, 0x8 + lsr r3, r7, 0x18 + st r0, (sp) + bmask r4, 0x8 + bmask r5, 0x8 + b loc_EC96376 +; --------------------------------------------------------------------------- + +loc_EC96354: ; CODE XREF: is_licensed+96j + lea r1, 0xF8(pc) + addcmpbeq r6, 0, 0, loc_EC96362 + lea r2, 0x772(gp) ; XREF 0xEE85032 aEncode_0 ; "encode" + b loc_EC96366 +; --------------------------------------------------------------------------- + +loc_EC96362: ; CODE XREF: is_licensed+C8j + lea r2, 0x779(gp) ; XREF 0xEE85039 aDecode_0 ; "decode" + +loc_EC96366: ; CODE XREF: is_licensed+D0j + lsr r3, r7, 0x10 + lsr r4, r7, 0x8 + bmask r3, 0x8 + bmask r4, 0x8 + bmask r5, r7, 0x8 + +loc_EC96376: ; CODE XREF: is_licensed+C2j + mov r0, r8 + bl sub_EDCA1AA + bl sub_EC8242E + cmp r7, 0x4D504732 + mov r9, r0 + cmpeq r6, 0 + bne loc_EC963A8 + mov r0, 0x2D + mov r1, 0 + bl sub_ECE7894 + mov r3, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, return_2 + +loc_EC963A8: ; CODE XREF: is_licensed+FCj + cmp r7, 0x57564331 + cmpeq r6, 0 + bne loc_EC963CE + mov r0, 0x2E + mov r1, 0 + bl sub_ECE7894 + mov r3, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, return_2 + +loc_EC963CE: ; CODE XREF: is_licensed+122j + mov r0, r8 + mov r1, 0 + bl sub_ED60C5A + mov r8, r0 + b loc_EC963E0 +; --------------------------------------------------------------------------- + +return_2: ; CODE XREF: is_licensed+114j + ; is_licensed+13Aj ... + mov r0, 0x2 + b return +; --------------------------------------------------------------------------- + +loc_EC963DE: ; CODE XREF: is_licensed+180j + add r8, 1 + +loc_EC963E0: ; CODE XREF: is_licensed+148j + ; is_licensed+17Cj + addcmpbeq r8, 0, 0, return_0 + mov r0, r8 + mov r1, 0 + mov r2, 0 + bl sub_EDCC4FA + mov r10, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + mov r3, r10 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, loc_EC96412 + mov r0, r8 + mov r1, 0x2C + bl sub_EDCBC50 + mov r8, r0 + addcmpbeq r8, 0, 0, loc_EC963E0 + b loc_EC963DE +; --------------------------------------------------------------------------- + +loc_EC96412: ; CODE XREF: is_licensed+16Cj + cmp r7, 0x4D504732 + cmpeq r6, 0 + bne loc_EC9642A + mov r0, 0x2D + mov r1, 0 + mov r2, r10 + bl sub_EDBF492 + +loc_EC9642A: ; CODE XREF: is_licensed+18Cj + cmp r7, 0x57564331 + cmpeq r6, 0 + bne return_2 + mov r0, 0x2E + mov r1, 0 + mov r2, r10 + bl sub_EDBF492 + b return_2 +; --------------------------------------------------------------------------- + +return_0: ; CODE XREF: is_licensed:loc_EC963E0j + mov r0, 0 + +return: ; CODE XREF: is_licensed+88j + ; is_licensed+14Cj + lea sp, 0x10(sp) + ldm r6-r16, pc, (sp++) +; End of function is_licensed + +; --------------------------------------------------------------------------- + nop + +loc_EC9644C: ; DATA XREF: is_licensed:loc_EC96354r + bitclear r5, 0x12 + ld r15, (r5+0x14) + ld r3, (r6+0x14) + ld r3, (r6+0x14) + bl r3 + bkpt +; --------------------------------------------------------------------------- +aS_CCCC .ascii "%s_%c%c%c%c",0 ; DATA XREF: is_licensed+9Ar + +; =============== S U B R O U T I N E ======================================= + + +sub_EC96464: ; CODE XREF: sub_ED48C70+A2p + stm r6-r18, lr, (--sp) diff --git a/sub_EC96290.asm b/sub_EC96290.asm new file mode 100644 index 0000000..7edb9ae --- /dev/null +++ b/sub_EC96290.asm @@ -0,0 +1,209 @@ + + + +; =============== S U B R O U T I N E ======================================= + + +sub_EC96290: ; CODE XREF: sub_EC64B68+10Ap + ; sub_EC960D4+D8p ... + stm r6-r16, lr, (--sp) + mov r7, r0 + lea sp, 0xFFFFFFF0(sp) + mov r6, r1 + cmp r7, 0x48323633 + beq loc_EC96316 + cmp r7, 0x48323634 + beq loc_EC96316 + cmp r7, 0x4D564330 + beq loc_EC96316 + cmp r7, 0x4D504734 + beq loc_EC96316 + cmp r7, 0x4D4A5041 + beq loc_EC96316 + cmp r7, 0x4D4A5042 + beq loc_EC96316 + cmp r7, 0x4D4A5047 + beq loc_EC96316 + cmp r7, 0x41474946 + beq loc_EC96316 + cmp r7, 0x50434D + beq loc_EC96316 + cmp r7, 0x574D5639 + bne loc_EC962EE + mov r7, 0x57564331 + +loc_EC962EE: ; CODE XREF: sub_EC96290+56j + cmp r7, 0x4D504732 + cmpeq r6, 0 + bne loc_EC96302 + ld r1, 0x1DC0(gp) ; XREF 0xEE86680 dword_EE86680 + addcmpbne r1, 0, 0, loc_EC96316 + +loc_EC96302: ; CODE XREF: sub_EC96290+68j + cmp r7, 0x57564331 + cmpeq r6, 0 + bne loc_EC9631C + ld r2, 0x2120(gp) ; XREF 0xEE869E0 dword_EE869E0 + addcmpbeq r2, 0, 0, loc_EC9631C + +loc_EC96316: ; CODE XREF: sub_EC96290+Ej + ; sub_EC96290+16j ... + mov r0, 1 + b loc_EC96446 +; --------------------------------------------------------------------------- + +loc_EC9631C: ; CODE XREF: sub_EC96290+7Cj + ; sub_EC96290+82j + mov r5, r7 + lea r8, 0x4(sp) + and r5, 0xFF000000 + addcmpbeq r5, 0, 0, loc_EC96354 + lea r1, 0x12E(pc) ; "%s_%c%c%c%c" + addcmpbeq r6, 0, 0, loc_EC96338 + lea r2, 0x764(gp) ; XREF 0xEE85024 aEncode ; "encode" + b loc_EC9633C +; --------------------------------------------------------------------------- + +loc_EC96338: ; CODE XREF: sub_EC96290+9Ej + lea r2, 0x76B(gp) ; XREF 0xEE8502B aDecode ; "decode" + +loc_EC9633C: ; CODE XREF: sub_EC96290+A6j + lsr r4, r7, 0x10 + lsr r5, r7, 0x8 + bmask r0, r7, 0x8 + lsr r3, r7, 0x18 + st r0, (sp) + bmask r4, 0x8 + bmask r5, 0x8 + b loc_EC96376 +; --------------------------------------------------------------------------- + +loc_EC96354: ; CODE XREF: sub_EC96290+96j + lea r1, 0xF8(pc) + addcmpbeq r6, 0, 0, loc_EC96362 + lea r2, 0x772(gp) ; XREF 0xEE85032 aEncode_0 ; "encode" + b loc_EC96366 +; --------------------------------------------------------------------------- + +loc_EC96362: ; CODE XREF: sub_EC96290+C8j + lea r2, 0x779(gp) ; XREF 0xEE85039 aDecode_0 ; "decode" + +loc_EC96366: ; CODE XREF: sub_EC96290+D0j + lsr r3, r7, 0x10 + lsr r4, r7, 0x8 + bmask r3, 0x8 + bmask r4, 0x8 + bmask r5, r7, 0x8 + +loc_EC96376: ; CODE XREF: sub_EC96290+C2j + mov r0, r8 + bl sub_EDCA1AA + bl sub_EC8242E + cmp r7, 0x4D504732 + mov r9, r0 + cmpeq r6, 0 + bne loc_EC963A8 + mov r0, 0x2D + mov r1, 0 + bl sub_ECE7894 + mov r3, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, loc_EC963DA + +loc_EC963A8: ; CODE XREF: sub_EC96290+FCj + cmp r7, 0x57564331 + cmpeq r6, 0 + bne loc_EC963CE + mov r0, 0x2E + mov r1, 0 + bl sub_ECE7894 + mov r3, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, loc_EC963DA + +loc_EC963CE: ; CODE XREF: sub_EC96290+122j + mov r0, r8 + mov r1, 0 + bl sub_ED60C5A + mov r8, r0 + b loc_EC963E0 +; --------------------------------------------------------------------------- + +loc_EC963DA: ; CODE XREF: sub_EC96290+114j + ; sub_EC96290+13Aj ... + mov r0, 0x2 + b loc_EC96446 +; --------------------------------------------------------------------------- + +loc_EC963DE: ; CODE XREF: sub_EC96290+180j + add r8, 1 + +loc_EC963E0: ; CODE XREF: sub_EC96290+148j + ; sub_EC96290+17Cj + addcmpbeq r8, 0, 0, loc_EC96444 + mov r0, r8 + mov r1, 0 + mov r2, 0 + bl sub_EDCC4FA + mov r10, r0 + mov r0, r9 + mov r1, r7 + mov r2, 0 + mov r3, r10 + bl sub_EC9DB40 + addcmpbne r0, 0, 0, loc_EC96412 + mov r0, r8 + mov r1, 0x2C + bl sub_EDCBC50 + mov r8, r0 + addcmpbeq r8, 0, 0, loc_EC963E0 + b loc_EC963DE +; --------------------------------------------------------------------------- + +loc_EC96412: ; CODE XREF: sub_EC96290+16Cj + cmp r7, 0x4D504732 + cmpeq r6, 0 + bne loc_EC9642A + mov r0, 0x2D + mov r1, 0 + mov r2, r10 + bl sub_EDBF492 + +loc_EC9642A: ; CODE XREF: sub_EC96290+18Cj + cmp r7, 0x57564331 + cmpeq r6, 0 + bne loc_EC963DA + mov r0, 0x2E + mov r1, 0 + mov r2, r10 + bl sub_EDBF492 + b loc_EC963DA +; --------------------------------------------------------------------------- + +loc_EC96444: ; CODE XREF: sub_EC96290:loc_EC963E0j + mov r0, 0 + +loc_EC96446: ; CODE XREF: sub_EC96290+88j + ; sub_EC96290+14Cj + lea sp, 0x10(sp) + ldm r6-r16, pc, (sp++) +; End of function sub_EC96290 + +; --------------------------------------------------------------------------- + nop + +loc_EC9644C: ; DATA XREF: sub_EC96290:loc_EC96354r + bitclear r5, 0x12 + ld r15, (r5+0x14) + ld r3, (r6+0x14) + ld r3, (r6+0x14) + bl r3 + bkpt +; --------------------------------------------------------------------------- +aS_CCCC .ascii "%s_%c%c%c%c",0 ; DATA XREF: sub_EC96290+9Ar