I compile this code

1.  #include <stdio.h>
2.  void F(int a, int b)
3.  {
4.  int c= a+b;
5.  int d= a*b; 
6. }


7.  void printAll()
8.  {
9.    printf("test1");
10.   printf("test2");
11.   printf("after a+b");
12.   printf("test4");
13.  }

and get this code

F(int, int):
        str     fp, [sp, #-4]!
        add     fp, sp, #0
        sub     sp, sp, #20
        str     r0, [fp, #-16]
        str     r1, [fp, #-20]
        ldr     r2, [fp, #-16]
        ldr     r3, [fp, #-20]
        add     r3, r2, r3
        str     r3, [fp, #-8]
        ldr     r3, [fp, #-16]
        ldr     r2, [fp, #-20]
        mul     r3, r2, r3
        str     r3, [fp, #-12]
        mov     r0, r0    @ nop
        sub     sp, fp, #0
        ldr     fp, [sp], #4
        bx      lr
.LC0:
        .ascii  "test1\000"
.LC1:
        .ascii  "test2\000"
.LC2:
        .ascii  "after a+b\000"
.LC3:
        .ascii  "test4\000"
printAll():
        stmfd   sp!, {fp, lr}
        add     fp, sp, #4
        ldr     r0, .L3
        bl      printf
        ldr     r0, .L3+4
        bl      printf
        ldr     r0, .L3+8
        bl      printf
        ldr     r0, .L3+12
        bl      printf
        mov     r0, r0    @ nop
        sub     sp, fp, #4
        ldmfd   sp!, {fp, lr}
        bx      lr
.L3:
        .word   .LC0
        .word   .LC1
        .word   .LC2
        .word   .LC3

I understanad all of this code, that no a problem.

what I want to understand is how can I patch a branch.

I want to edit my binary file without damage the offset of function and after this line int c= a+b; I want to jump to this line printf("after a+b"); and then go back to int d= a*b;

I think I need to add 2 branch (B) instructions : 1 between lines 4-5 and second is between 10-11

So, after I finish lines 4, I jump to line 11 and when I finish lines 11 I jump to line 5.

Is that the right way to do this?

  1. I did not found how to write B (branch) instruction in hex, and how can I know what is the address where to jump by reading the binary file (with Ida).

  2. Is that the right way ? use on B instruction ?

  3. I not have a problem to remove some line on printAll function so I not afraid to add there label and branch instructions (I can remove line 9 and then I have space to patch 2 instructions ). But I can't remove any instructions from F function, how can I do it ?

  • 1
    labels are only artificial way of marking offsets/addresses in assembly. There are none in the binary. – Paweł Łukasik Mar 19 at 12:44
  • so I only need to add 2 branch instructions ? is that the beast way to do what I need? – arm Mar 19 at 12:46
  • show the disassembly of the code in the object file, not the assembly code generated by the compiler from the source code. – julian Mar 19 at 12:51
  • @SYS_V I ask about the assembly that I show, that general quastion , after that I see how can I include you answer on my code. – arm Mar 19 at 13:04
  • You say you want to edit the binary file, so show the code in the binary file. – julian Mar 19 at 13:08

I took Your code inserted some #defines that are needed to compile arm in vc2017 community dev prompt

modified your printall() to main() so that there is an entry point defined

inserted a call to F() so that it is easily identifiable and loaded the compiled exe into radare2

modified code

//#defines to make vs2017 community build arm 
// need to pass -arch-arm -host_arch=x86 or appropriate  host_arch
// i compiled this on x86 32 so i passed x86 to vsdevcmd.bat
// and compiled with cl foo.cpp
#define _CRT_BUILD_DESKTOP_APP 1
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <stdio.h>
void F(int a, int b) {
    int c= a+b;
    int d= a*b;
}
void main() {
    printf("test1");
    printf("test2");
    printf("after a+b");
    printf("test4");
    // call F() inserted so it is easily identifiable 
    // and / or not thrown away by compiler for no ref 
    F(4,5); 
}

compiled linked and opened up the exe in radare2

>cl armie.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.13.26128 for ARM
Copyright (C) Microsoft Corporation.  All rights reserved.

armie.cpp
Microsoft (R) Incremental Linker Version 14.13.26128.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:armie.exe
/machine:arm
armie.obj

>radare2 -AA armie.exe
←[32m[x]←[0m Analyze all flags starting with sym. and entry0 (aa)
[ ] ←[33m
[←[0mValue from 0x00401000 to 0x00417000
aav: 0x00401000-0x00417000 in 0x401000-0x417000
←[32m[x]←[0m Analyze len bytes of instructions for references (aar)
←[32m[x]←[0m Analyze function calls (aac)
←[32m[x]←[0m Emulate code to find computed references (aae)
←[32m[x]←[0m Analyze consecutive function (aat)
←[32m[x]←[0m Constructing a function name for fcn.* and sym.func.* functions (aan)
←[32m[x]←[0m Type matching analysis for all functions (afta)
 -- Run a command with unspecified long sequence of 'a', 
 pancake will be summoned and do the analysis for you.
[0x00401fa0]>

the disassembly of the mainfunction

looking for string refs
[0x00401fa0]> iz~test
000 0x0000c550 0x0040d150   5   6 (.rdata) ascii test1

looking for xrefs to string refs
[0x00401fa0]> axt 0x40d150
(nofunc) 0x401d48 [null] subeq sp, r0, r0, asr r1
fcn.00401d08 0x401d10 [data] invalid

printing the disassembly of the referred function     
[0x00401fa0]> pdf @ fcn.00401d08
/ (fcn) fcn.00401d08 52
|   fcn.00401d08 ();
|              ; UNKNOWN XREF from 0x00401f46 (aav.0x00401e85 + 193)
|              ; CALL XREF from 0x00401f46 (aav.0x00401e85 + 193)
|           0x00401d08      2de90048       push.w {fp, lr}
|           0x00401d0c      eb46           mov fp, sp
|           0x00401d0e      82b0           sub sp, 8
|           0x00401d10      0d48           ldr r0, str.test1  ; [0x40d150:4]=0x ; "test1"
|           0x00401d12      00f04bf8       bl fcn.00401dac
|           0x00401d16      0b48           ldr r0, str.test2  ; [0x40d158:4]=0x ; "test2"
|           0x00401d18      00f048f8       bl fcn.00401dac
|           0x00401d1c      0848           ldr r0, str.after_a_b;[0x40d160:4]=; "after a+b"
|           0x00401d1e      00f045f8       bl fcn.00401dac
|           0x00401d22      0648           ldr r0, str.test4  ; [0x40d16c:4]=0x ; "test4"
|           0x00401d24      00f042f8       bl fcn.00401dac
|           0x00401d28      0521           movs r1, 5         ; 5
|           0x00401d2a      0420           movs r0, 4         ; 4
|           0x00401d2c      fff7d8ff       bl fcn.00401ce0
|           0x00401d30      0023           movs r3, 0
|           0x00401d32      0093           str r3, [sp]
|           0x00401d34      0098           ldr r0, [sp]
|           0x00401d36      02b0           add sp, 8
\           0x00401d38      bde80088       pop.w {fp, pc}
[0x00401fa0]>

so you can see your F() is at 0x401ce0

[0x00401fa0]> pdf @0x401ce0
/ (fcn) fcn.00401ce0 38
|   fcn.00401ce0 ();
|              ; UNKNOWN XREF from 0x00401d2c (fcn.00401d08)
|              ; CALL XREF from 0x00401d2c (fcn.00401d08)
|           0x00401ce0      03b4           push {r0, r1}
|           0x00401ce2      2de90048       push.w {fp, lr}
|           0x00401ce6      eb46           mov fp, sp
|           0x00401ce8      82b0           sub sp, 8
|           0x00401cea      049a           ldr r2, [sp, 0x10]
|           0x00401cec      059b           ldr r3, [sp, 0x14]
|           0x00401cee      1344           add r3, r2
|           0x00401cf0      0093           str r3, [sp]
damage here and insert an unconditional jump if it is 2 bytes 1cf2
will be damaged if more bytes more instruction will be damaged 
before print save what you need to restore back do the printf 
restore what you damage and jump back to a valid address 
|           0x00401cf2      049a           ldr r2, [sp, 0x10]
|           0x00401cf4      059b           ldr r3, [sp, 0x14]
|           0x00401cf6      02fb03f3       mul r3, r2, r3
|           0x00401cfa      0193           str r3, [sp, 4]
|           0x00401cfc      02b0           add sp, 8
|           0x00401cfe      5df804bb       ldr fp, [sp], 4
\           0x00401d02      5df80cfb       ldr pc, [sp], 0xc
[0x00401fa0]>

so you need to print after a+b after the address 0x00401cee 1344 add r3, r2

so you should jump from this address to 0x401d1c in the process if you damage the str instruction you may need to restore it in some new place (code caves some new added section whatever

EDIT
assuming you patched 6 bytes from 0x401cf2 and jumped to 0x401d1c there you should recreate the 6 bytes before or after you do your printf() and jumping back

address bytes original -> address patched bytes -> jmping to new location->
save the needed registers (if on x86 pushad / pushf / popad / popf instructions find equivalent for that in arm if there is no wholesale register saving instructions save them individually )
after that execute your printf
after executing printf repatch the damaged bytes and then patch a jmp back instruction so that the damaged instructions are executed prior to jumping back

patching with arm windbg

:\>cdb -z armie.exe
the complete function disassembly of F()

Microsoft (R) Windows Debugger Version 10.0.16299.15 X86

0:000> uf 401ce0
armie+0x1ce0:
00401ce0 b403     push        {r0,r1}
00401ce2 e92d4800 push        {r11,lr}
00401ce6 46eb     mov         r11,sp
00401ce8 b082     sub         sp,sp,#8
00401cea 9a04     ldr         r2,[sp,#0x10]
00401cec 9b05     ldr         r3,[sp,#0x14]
00401cee 4413     add         r3,r3,r2
00401cf0 9300     str         r3,[sp]
00401cf2 9a04     ldr         r2,[sp,#0x10] <<< patch here 
00401cf4 9b05     ldr         r3,[sp,#0x14]
00401cf6 fb02f303 mul         r3,r2,r3
00401cfa 9301     str         r3,[sp,#4]
00401cfc b002     add         sp,sp,#8
00401cfe f85dbb04 pop         {r11}
00401d02 f85dfb0c ldr         pc,[sp],#0xC

patching at 401cf2 and redisassembling to see if b label patch is correct or not windbg uf does control flow and shows it will execute the jmp and printf

0:000> eb 401cf2 11 e0
0:000> uf 401ce0

armie+0x1ce0:
00401ce0 b403     push        {r0,r1}
00401ce2 e92d4800 push        {r11,lr}
00401ce6 46eb     mov         r11,sp
00401ce8 b082     sub         sp,sp,#8
00401cea 9a04     ldr         r2,[sp,#0x10]
00401cec 9b05     ldr         r3,[sp,#0x14]
00401cee 4413     add         r3,r3,r2
00401cf0 9300     str         r3,[sp]

> (( 0xe011 & 0b0000011111111111 ) << 1 )+4 + 0x401cf2
ans = 0x00401D18

00401cf2 e011     b           armie+0x1d18 (00401d18) <<< we jumped to printf here 
damaged two bytes we need to restore it back when we jump back

armie+0x1d18:
00401d18 f000f848 bl          armie+0x1dac (00401dac)
00401d1c 4808     ldr         r0,=armie+0xd160 (0040d160) ; [armie+0x1d40 (00401d40)]
00401d1e f000f845 bl          armie+0x1dac (00401dac)
-=xxxxxxxxxxxxxxxxxxxxxx===- 
0:000> u 401cf2
armie+0x1cf2:
00401cf2 e011     b           armie+0x1d18 (00401d18)
00401cf4 9b05     ldr         r3,[sp,#0x14]  <<<< only two bytes damaged by patch you need 
to put them back after printf a+b before jumping back here 
00401cf6 fb02f303 mul         r3,r2,r3
00401cfa 9301     str         r3,[sp,#4]

0:000> 

btw if you want to generate bytes for patching like say b label instruction you can use the visual studio armasm like this

:\>dir /b *.obj
File Not Found

:\>cat myasm.asm
    AREA .text, CODE, ARM
test PROC
    b (0x401d18-0x401cf2)
    ENDP
    END
:\>armasm myasm.asm
Microsoft (R) ARM Macro Assembler Version 14.13.26128.0
Copyright (C) Microsoft Corporation.  All rights reserved.


:\>dir /b *.obj
myasm.obj

:\>link -dump -disasm myasm.obj
Microsoft (R) COFF/PE Dumper Version 14.13.26128.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file myasm.obj

File Type: COFF OBJECT

test:
  00000000: E011      b           00000026

  Summary

          74 .debug$S
           2 .text

:\>
  • if I add branch to 0x401d1c after 0x00401cee so all the instructions will changes address – arm Mar 19 at 21:06
  • if I add new instruction after 0x00401cee so he new instruction will be locate in 0x00401cf0 and so that all of instructions changed place , so all the link (function call and offset will damage) – arm Mar 19 at 21:12
  • i added a comment on how you are supposed to patch in the answer see if that makes any sense – blabb Mar 19 at 21:33
  • I read your comment but I not get you, can you please explain again? I think that if I add branch so all the offset on binary file will damade. If I edit instruction to branch ( if it less or equal byte compare to branch) so the instruction that I replace will missing to binary – arm Mar 19 at 22:18
  • not sure get someone to translate the comment what i meant is you should overwrite the bytes and then in the destination after you do what you want to do you should also do all the operations that you destroyed while patching – blabb Mar 20 at 4:43

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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