Any ideas why trying to patch a ARMv7 binary causes a segfault while basically the same patch on the Win64 version of the software works as expected?

Here is the Win64 version, that works

    UPX0:00000001406AEB39 InvLicenseCheck:                        ; CODE XREF: sub_1406AE6D0+53↑j
    UPX0:00000001406AEB39                                         ; sub_1406AE6D0+72↑j ...
    UPX0:00000001406AEB39                 jmp     short JumpHere
    UPX0:00000001406AEB3B ; ---------------------------------------------------------------------------
    UPX0:00000001406AEB3B                 nop
    UPX0:00000001406AEB3C                 nop
    UPX0:00000001406AEB3D                 nop
    UPX0:00000001406AEB3E                 call    cs:__imp___acrt_iob_func
    UPX0:00000001406AEB44                 lea     rdx, aInvalidLicense_1 ; "Invalid License\r\n"
    UPX0:00000001406AEB4B                 mov     rcx, rax
    UPX0:00000001406AEB4E                 call    sub_14066C780
    UPX0:00000001406AEB53                 lea     rdx, aInvalidLicense_0 ; "Invalid License"
    UPX0:00000001406AEB5A                 mov     ecx, 3
    UPX0:00000001406AEB5F                 call    sub_14068EEA0
    UPX0:00000001406AEB64                 mov     ecx, 1          ; Count
    UPX0:00000001406AEB69                 mov     edx, 34h        ; Size
    UPX0:00000001406AEB6E                 call    calloc
    UPX0:00000001406AEB73                 mov     rbx, rax
    UPX0:00000001406AEB76                 mov     rax, 736E6563696C6E75h
    UPX0:00000001406AEB80                 mov     [rbx], rax
    UPX0:00000001406AEB83                 mov     dword ptr [rbx+7], 646573h
    UPX0:00000001406AEB8A                 mov     dword ptr [rbx+28h], 1
    UPX0:00000001406AEB91                 mov     byte ptr [rbx+30h], 1
    UPX0:00000001406AEB95 JumpHere:                               ; CODE XREF: sub_1406AE6D0:InvLicenseCheck↑j
    UPX0:00000001406AEB95                                         ; sub_1406AE6D0+51F↓j
    UPX0:00000001406AEB95                 mov     rcx, r13        ; Memory
    UPX0:00000001406AEB98                 call    free
    UPX0:00000001406AEB9D                 mov     rax, rbx
    UPX0:00000001406AEBA0                 add     rsp, 278h
    UPX0:00000001406AEBA7                 pop     rbx
    UPX0:00000001406AEBA8                 pop     rbp
    UPX0:00000001406AEBA9                 pop     rdi
    UPX0:00000001406AEBAA                 pop     rsi
    UPX0:00000001406AEBAB                 pop     r12
    UPX0:00000001406AEBAD                 pop     r13
    UPX0:00000001406AEBAF                 pop     r14
    UPX0:00000001406AEBB1                 pop     r15
    UPX0:00000001406AEBB3                 retn
    UPX0:00000001406AEBB4 ; ---------------------------------------------------------------------------

And the ARMv7l version, which gives a signal 11 (segfault).

This is odd because I've stepped through the patch in GDB and the patch itself does not cause the segfault...

    LOAD:000447C4 InvLicenseCheck                         ; CODE XREF: sub_44664+4C↑j
    LOAD:000447C4                                         ; sub_44664+64↑j ...
    LOAD:000447C4                 B               JumpHere ; Keypatch modified this from:
    LOAD:000447C4                                         ;   LDR R3, =off_135004
    LOAD:000447C8 ; ---------------------------------------------------------------------------
    LOAD:000447C8                 MOV             R2, #0x10
    LOAD:000447CC                 LDR             R3, [R3]
    LOAD:000447D0                 MOV             R1, #1
    LOAD:000447D4                 LDR             R0, =aInvalidLicense_0 ; "Invalid License\n"
    LOAD:000447D8                 BL              sub_F4850
    LOAD:000447DC                 LDR             R1, =aInvalidLicense ; "Invalid License"
    LOAD:000447E0                 MOV             R0, #3
    LOAD:000447E4                 BL              sub_5079C
    LOAD:000447E8                 MOV             R1, #0x34 ; Count
    LOAD:000447EC                 MOV             R0, #1  ; Size
    LOAD:000447F0                 BL              calloc  ; calloc
    LOAD:000447F4                 LDR             R3, =aUnlicensed ; "unlicensed"
    LOAD:000447F8                 MOV             R7, R0
    LOAD:000447FC                 LDMIA           R3, {R0-R2} ; "unlicensed"
    LOAD:00044800                 MOV             R3, R7
    LOAD:00044804                 STMIA           R3!, {R0,R1}
    LOAD:00044808                 MOV             R12, R2,LSR#16
    LOAD:0004480C                 MOV             R1, #1
    LOAD:00044810                 STRH            R2, [R3],#2
    LOAD:00044814                 STRB            R12, [R3]
    LOAD:00044818                 STR             R1, [R7,#0x28]
    LOAD:0004481C                 STRB            R1, [R7,#0x30]
    LOAD:00044820 JumpHere                                ; CODE XREF: sub_44664:InvLicenseCheck↑j
    LOAD:00044820                                         ; sub_44664+454↓j
    LOAD:00044820                 MOV             R0, R5  ; Memory
    LOAD:00044824                 BL              cfree   ; cfree
    LOAD:00044828                 MOV             R0, R7
    LOAD:0004482C                 ADD             SP, SP, #0x184
    LOAD:00044830                 LDMFD           SP!, {R4-R11,PC}
    LOAD:00044834 ; ---------------------------------------------------------------------------

I'm not very well versed in debugging on linux, let alone on the ARM platform. Any hints would be welcome.

  • I'm surprised that it works in the x86 code. At the very least, you have an apparently uninitialised RBX value (and corresponding R7 in the ARM code). Does the segfault occur within this routine, or after it returns? You might have gotten lucky that RBX points to something writable, but R7 does not. Commented Jun 12, 2022 at 5:48
  • The segfault occurs quite a few calls after the JumpHere segment, all the way in 0x107EC (which seems completely unrelated). I've tried making it jump to after the free call aswell incase it was doing something weird to the memory. I've also attempted to patch each BL with a NOP (mov r0, r0) instead of doing a branch at the beginning. After some more investigating on the x64 binary, it looks like it sets up the return values for the function starting at 1406AEB64, so I will try branching to there instead directly to JumpHere and see if I can implement the same on the ARM binary.
    – captmicr0
    Commented Jun 12, 2022 at 7:01

1 Answer 1


Do you know the difference between jmp (B) and call (BL)? Read about return address, which is saved in the LR register (ARM) for 'BL'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.