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
:\>