├── README.md ├── nrf52832 ├── .gdb_history ├── add.sh ├── execute_firmware.py ├── model │ ├── PeriModel.py │ ├── add.sh │ ├── add_input │ ├── inf.hex │ ├── inf.out │ └── peri_write.txt └── result.txt ├── stm32f1 ├── add.sh ├── execute_firmware.py ├── model │ ├── PeriModel.py │ ├── add.sh │ ├── add_input │ ├── peri_write.txt │ ├── program.elf │ └── result.txt └── result.txt └── stm32f4 ├── add.sh ├── execute_firmware.py ├── model ├── PeriModel.py ├── add.sh ├── add_input ├── peri_write.txt ├── program.elf └── result.txt └── result.txt /README.md: -------------------------------------------------------------------------------- 1 | # AutoMap 2 | Emulator plugin to emulate MCU based firmware. It discovers hidden memory mappings between peripheral registers. 3 | 4 | For more details, please refer to our paper [What You See is Not What You Get: Revealing Hidden Memory Mapping for Peripheral Modeling](https://web.cse.ohio-state.edu/~lin.3021/file/RAID22.pdf) 5 | 6 | ## How to run it 7 | There are three MCUs, NRF52832, STM32F103, and STM32F429. To emulate NRF52832, it requires JLinkGDBServer. You can download it from the [website](https://www.segger.com/products/debug-probes/j-link/tools/j-link-gdb-server/about-j-link-gdb-server/). To emulate STM32F103 and STM32F429, it reuiqes the tool named openocd. You can install openocd through the below command. 8 | ``` 9 | sudo apt-get install openocd 10 | ``` 11 | 12 | ### Run NRF52832 13 | Open two terminals and execute the below command in one terminal. 14 | ``` 15 | /usr/bin/JLinkGDBServer -If SWD -Speed 4000 -Device Cortex-M4 16 | ``` 17 | 18 | Then, in another terminal, execute the below command after adding your target firmware in the `add.sh` file. 19 | ``` 20 | ./add.sh 21 | ``` 22 | 23 | ### Run STM32 24 | Open two terminals and execute the below command in one terminal based on your target MCU. 25 | ``` 26 | openocd -f interface/stlink-v2-1.cfg -f target/stm32f1x_stlink.cf 27 | openocd -f interface/stlink-v2-1.cfg -f target/stm32f4x_stlink.cfg 28 | ``` 29 | 30 | Then, in another terminal, execute the below command after adding your target firmware in the `add.sh` file. 31 | ``` 32 | ./add.sh 33 | ``` 34 | 35 | 36 | ## Citation 37 | 38 | If you create a research work that uses our work, please cite our paper: 39 | 40 | ``` 41 | @inproceedings{won2022you, 42 | title={What You See is Not What You Get: Revealing Hidden Memory Mapping for Peripheral Modeling}, 43 | author={Won, Jun Yeon and Wen, Haohuang and Lin, Zhiqiang}, 44 | booktitle={25th International Symposium on Research in Attacks, Intrusions and Defenses}, 45 | pages={200--213}, 46 | year={2022} 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /nrf52832/.gdb_history: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/nrf52832/.gdb_history -------------------------------------------------------------------------------- /nrf52832/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true 4 | do 5 | rm -f model/add_regs.txt 6 | ./execute_firmware.py --firmware 7 | FILE=model/add_regs.txt 8 | if [ -f "$FILE" ]; then 9 | cat $FILE 10 | cd model 11 | ./add.sh 12 | cd ../ 13 | else 14 | break 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /nrf52832/execute_firmware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | import os 5 | import sys 6 | import random 7 | from unicorn import * 8 | from unicorn.arm_const import * 9 | from capstone import * 10 | import argparse 11 | import codecs 12 | import binascii 13 | import time 14 | import os.path 15 | 16 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_MCLASS) 17 | cs = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS) 18 | 19 | peri_init = {} 20 | peri_bits = {} 21 | peri_type = {} 22 | peri_banding = {} 23 | set_bits = [] 24 | 25 | flag = 0 26 | 27 | before_value = 0 28 | before_addr = 0 29 | 30 | global_base_addr = 0 31 | 32 | clock = 0 33 | 34 | def arg_parser(): 35 | parser = argparse.ArgumentParser() 36 | parser.add_argument('--firmware', type=str, help="firmware binary") 37 | parser.add_argument('--base_addr', type=int, default=0x0, help="the base address of firmware") 38 | 39 | return parser.parse_args() 40 | 41 | def bytes_to_int(inputs): 42 | result = 0 43 | inputs = inputs[::-1] 44 | for b in inputs: 45 | result = result * 256 + int (b) 46 | 47 | return long(result) 48 | 49 | def int_to_hex_rev(value): 50 | value = int(value) 51 | hex_str = '%08x' %value 52 | str_to_convert = hex_str[6:8] + hex_str[4:6] + hex_str[2:4] + hex_str[0:2] 53 | return codecs.decode(str_to_convert, "hex") 54 | 55 | 56 | def debug_instruction(uc, address, size, user_data): 57 | global flag 58 | global global_base_addr 59 | 60 | global clock 61 | uc.mem_write(0xe000e018, int_to_hex_rev(clock)) 62 | uc.mem_write(0xe0001004, int_to_hex_rev(clock)) 63 | clock = clock + 0x100 64 | 65 | if flag == 1: 66 | flag = 0 67 | global set_bits 68 | global before_value 69 | global before_addr 70 | 71 | for addr_dict in set_bits: 72 | for addr in addr_dict: 73 | value = addr_dict[addr] 74 | prev_value = bytes_to_int(uc.mem_read(addr, 4)) 75 | new_value = value 76 | uc.mem_write(addr, codecs.decode(format(new_value, '08x'), "hex")) 77 | 78 | def mem_read(uc, access, address, size, value, data): 79 | mem_value = bytes_to_int(uc.mem_read(address, 4)) 80 | 81 | if address >= 0x40000000: 82 | if address not in peri_init: 83 | output = '%x' %address 84 | fp = open('model/add_regs.txt', 'w') 85 | fp.write(output) 86 | fp.close() 87 | os._exit(1) 88 | 89 | return 90 | return 91 | 92 | def pre_mem_write(uc, access, address, size, value, data): 93 | if address >= 0x40000000: 94 | global flag 95 | global peri_banding 96 | global set_bits 97 | 98 | flag = 1 99 | if address not in peri_init: 100 | output = '%x' %address 101 | fp = open('model/add_regs.txt', 'w') 102 | fp.write(output) 103 | fp.write("\n") 104 | fp.write(str(value)) 105 | fp.close() 106 | os._exit(1) 107 | 108 | return 109 | 110 | global before_addr 111 | global before_value 112 | before_addr = address 113 | before_value = bytes_to_int(uc.mem_read(address, 4)) 114 | if address in peri_banding: 115 | band_list = peri_banding[address] 116 | 117 | for add_dict in band_list: 118 | for add_value in add_dict: 119 | if add_value == value: 120 | write_fp = open('model/peri_write.txt', 'a') 121 | output = '%x' %address 122 | write_fp.write(output) 123 | write_fp.write("\n") 124 | write_fp.write(str(value)) 125 | write_fp.write("\n") 126 | write_fp.close() 127 | set_bits = add_dict[add_value] 128 | return 129 | 130 | 131 | output = '%x' %address 132 | fp = open('model/add_regs.txt', 'w') 133 | fp.write(output) 134 | fp.write("\n") 135 | fp.write(str(value)) 136 | fp.close() 137 | os._exit(1) 138 | 139 | return 140 | 141 | return 142 | 143 | def init_peri_reg(): 144 | global peri_init 145 | 146 | for addr in peri_init: 147 | init_value = peri_init[addr] 148 | uc.mem_write(addr, int_to_hex_rev(init_value)) 149 | return 150 | 151 | 152 | def read_peripheral_model(): 153 | global peri_init 154 | global peri_banding 155 | 156 | 157 | if (os.path.isfile('model/result.txt') == False): 158 | return 159 | 160 | fp = open('model/result.txt', 'r') 161 | 162 | while True: 163 | line = fp.readline() 164 | 165 | if not line: 166 | break 167 | 168 | addr = (line.split())[1] 169 | addr = int(addr, 0) 170 | 171 | line = fp.readline() 172 | init_value = (line.split())[2] 173 | init_value = int(init_value, 0) 174 | 175 | if addr not in peri_init: 176 | peri_init[addr] = init_value 177 | 178 | 179 | line = fp.readline() 180 | if line == "\n": 181 | continue 182 | elif not line: 183 | break 184 | 185 | add_value = line.strip() 186 | add_value = int(add_value) 187 | bit_band = [] 188 | sub_banding = {} 189 | while True: 190 | band_addr = fp.readline() 191 | if band_addr == '\n': 192 | break 193 | 194 | addr_and_value = band_addr.strip().split() 195 | band_addr = addr_and_value[0] 196 | final_val = int(addr_and_value[1]) 197 | band_addr = int(band_addr, 0) 198 | value_pair = {} 199 | value_pair[band_addr] = final_val 200 | bit_band.append(value_pair) 201 | 202 | sub_banding[add_value] = bit_band 203 | 204 | if peri_banding.has_key(addr) == True: 205 | peri_banding[addr].append(sub_banding) 206 | else: 207 | peri_banding[addr] = [] 208 | peri_banding[addr].append(sub_banding) 209 | 210 | 211 | def map_elf_memory(filename): 212 | CODE_ADDR = 0x0 213 | STACK_SIZE = 0x8000 214 | 215 | CODE = open(filename).read() 216 | 217 | fp = open(filename, 'rb') 218 | 219 | stack_addr_rev = fp.read(4) 220 | entry_addr_rev = fp.read(4) 221 | 222 | stack_addr = "" 223 | entry_addr = "" 224 | 225 | for i in range(0, len(stack_addr_rev)): 226 | stack_addr += stack_addr_rev[3-i] 227 | entry_addr += entry_addr_rev[3-i] 228 | fp.close() 229 | 230 | START_ADDR = int(entry_addr.encode("hex"), 16) 231 | STACK_ADDR = int(stack_addr.encode("hex"), 16) 232 | 233 | 234 | SIZE = 0xfffff000 235 | uc.mem_map(0x0, SIZE) 236 | uc.mem_map(0xfffff000, 0x1000) 237 | 238 | FFlist = "FF" * 0x80000 239 | FFlist = codecs.decode(FFlist, "hex") 240 | uc.mem_write(0x0, FFlist) 241 | 242 | uc.mem_write(0x0, CODE) 243 | uc.reg_write(UC_ARM_REG_SP, STACK_ADDR) 244 | 245 | uc.hook_add(UC_HOOK_CODE, debug_instruction) 246 | uc.hook_add(UC_HOOK_MEM_WRITE, pre_mem_write) 247 | uc.hook_add(UC_HOOK_MEM_READ, mem_read) 248 | return START_ADDR 249 | 250 | def main(): 251 | args = arg_parser() 252 | 253 | read_peripheral_model() 254 | 255 | if (os.path.isfile('model/peri_write.txt') == True): 256 | os.remove('model/peri_write.txt') 257 | fp = open('model/peri_write.txt','w') 258 | fp.close() 259 | 260 | 261 | global peri_init 262 | global peri_bits 263 | global peri_type 264 | global peri_banding 265 | 266 | global global_base_addr 267 | global_base_addr = args.base_addr 268 | start_addr = map_elf_memory(args.firmware) 269 | 270 | init_peri_reg() 271 | 272 | uc.emu_start(start_addr | 1, 0, 0, count=200000) 273 | 274 | if __name__ == "__main__": 275 | main() 276 | -------------------------------------------------------------------------------- /nrf52832/model/PeriModel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import sys 6 | import random 7 | import codecs 8 | import binascii 9 | import subprocess 10 | import time 11 | 12 | done_list = [] 13 | flag = -1 14 | 15 | peri_addr_range = [] 16 | peri_mem_map_idx = [] 17 | 18 | def arg_parser(): 19 | parser = argparse.ArgumentParser() 20 | parser.add_argument('--peri_file', type=str, default="peri_regs.txt", help="file for the list of peripheral registers address") 21 | parser.add_argument('--bin_file', type=str, help="firmware binary file name") 22 | 23 | return parser.parse_args() 24 | 25 | def read_memory(base_addr, length, filetype): 26 | if os.path.exists(filetype): 27 | os.remove(filetype) 28 | gdb.execute("set logging file " + filetype) 29 | gdb.execute("set logging on") 30 | idx = 0 31 | while (idx < length): 32 | gdb.execute("x /4x " + str(hex(base_addr + idx))) 33 | idx = idx + 16 34 | 35 | gdb.execute("set logging off") 36 | fp = open(filetype, 'r') 37 | lines = fp.readlines() 38 | result = [] 39 | for line in lines: 40 | idx = 1 41 | for j in range(0, 4): 42 | addr = line.split()[idx] 43 | addr_val = int(addr, 16) 44 | for i in range(0, 4): 45 | result.append(addr_val % 256) 46 | addr_val = addr_val / 256 47 | idx = idx + 1 48 | 49 | return result 50 | 51 | def init_read_memory(base_addr, length, filetype): 52 | if os.path.exists(filetype): 53 | os.remove(filetype) 54 | gdb.execute("set logging file " + filetype) 55 | gdb.execute("set logging on") 56 | idx = 0 57 | while (idx < length): 58 | gdb.execute("x /x " + str(hex(base_addr + idx))) 59 | idx = idx + 4 60 | 61 | gdb.execute("set logging off") 62 | fp = open(filetype, 'r') 63 | lines = fp.readlines() 64 | result = [] 65 | for line in lines: 66 | addr = line.split()[1] 67 | addr_val = int(addr, 16) 68 | for i in range(0, 4): 69 | result.append(addr_val % 256) 70 | addr_val = addr_val / 256 71 | 72 | return result 73 | 74 | 75 | def bytes_to_int(inputs): 76 | result = 0 77 | inputs = inputs[::-1] 78 | 79 | for b in inputs: 80 | result = result * 256 + ord(b) 81 | 82 | return long(result) 83 | 84 | def get_peri_list(filename): 85 | fp = open(filename, 'r') 86 | 87 | addr = fp.readline() 88 | value = fp.readline() 89 | 90 | return addr, value 91 | 92 | def stepi(count): 93 | for i in range(count): 94 | gdb.execute('stepi') 95 | 96 | def reverse(str_val): 97 | temp = str_val[6:8] + str_val[4:6] + str_val[2:4] + str_val[0:2] 98 | return temp 99 | 100 | def start_gdb(filename): 101 | input_file = 'file ' + filename 102 | gdb.execute(input_file) 103 | gdb.execute('target remote localhost:2331') 104 | gdb.execute('mon speed 10000') 105 | gdb.execute('mon flash download=1') 106 | gdb.execute('load') 107 | gdb.execute('mon reset 0') 108 | gdb.execute('mon reset 0') 109 | gdb.execute('set pagination off') 110 | gdb.execute('set arm force-mode thumb') 111 | gdb.execute('set endian little') 112 | 113 | 114 | def build_model(peri_addr, value): 115 | 116 | gdb.execute('mon reset 0') 117 | 118 | l = gdb.inferiors()[0] 119 | 120 | global peri_addr_range 121 | global peri_mem_map_idx 122 | global done_list 123 | peri_addr = peri_addr.strip() 124 | peri_addr = int(peri_addr, 16) 125 | 126 | value = value.strip() 127 | value = int(value, 10) 128 | 129 | 130 | init_peri_val = l.read_memory(peri_addr, 4) 131 | init_peri_val = bytes_to_int(init_peri_val) 132 | 133 | ret = add_prev_peri() 134 | 135 | base_addr = 0x40000000 136 | length = 0x30000 137 | 138 | prev_first_mem = l.read_memory(base_addr, length) 139 | prev_second_mem = l.read_memory(0x50000000, 0x40000) 140 | prev_third_mem = l.read_memory(0xe0000000, 0x10000) 141 | prev_fourth_mem = l.read_memory(0xe0040000, 0x2000) 142 | prev_fifth_mem = l.read_memory(0xf0000000, 0x10000) 143 | prev_sixth_mem = l.read_memory(0xf0040000, 0x2000) 144 | 145 | if value < 0: 146 | str_val = format(4294967296 - value, '08x') 147 | else: 148 | str_val = format(value, '08x') 149 | 150 | str_val = reverse(str_val) 151 | str_val = codecs.decode(str_val, "hex") 152 | 153 | l.write_memory(peri_addr, str_val, 4) 154 | stepi(2000) 155 | 156 | next_first_mem = l.read_memory(base_addr, length) 157 | next_second_mem = l.read_memory(0x50000000, 0x40000) 158 | next_third_mem = l.read_memory(0xe0000000, 0x10000) 159 | next_fourth_mem = l.read_memory(0xe0040000, 0x2000) 160 | next_fifth_mem = l.read_memory(0xf0000000, 0x10000) 161 | next_sixth_mem = l.read_memory(0xf0040000, 0x2000) 162 | 163 | idx=0 164 | 165 | fp = open("./result.txt", 'a') 166 | fp.write("addr 0x%x information\n" %peri_addr) 167 | fp.write("initial value 0x%x\n" %init_peri_val) 168 | fp.write("%d\n" %value) 169 | 170 | 171 | idx=0 172 | peri_start_addr = 0x40000000 173 | while idx < len(prev_first_mem): 174 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 175 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 176 | elif prev_first_mem[idx:idx+4] != next_first_mem[idx:idx+4]: 177 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 178 | idx = idx + 4 179 | 180 | idx=0 181 | peri_start_addr = 0x50000000 182 | while idx < len(prev_second_mem): 183 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 184 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 185 | elif prev_second_mem[idx:idx+4] != next_second_mem[idx:idx+4]: 186 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 187 | idx = idx + 4 188 | 189 | idx=0 190 | peri_start_addr = 0xe0000000 191 | while idx < len(prev_third_mem): 192 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 193 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 194 | elif prev_third_mem[idx:idx+4] != next_third_mem[idx:idx+4]: 195 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 196 | idx = idx + 4 197 | 198 | idx=0 199 | peri_start_addr = 0xe0040000 200 | while idx < len(prev_fourth_mem): 201 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 202 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 203 | elif prev_fourth_mem[idx:idx+4] != next_fourth_mem[idx:idx+4]: 204 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 205 | idx = idx + 4 206 | 207 | idx=0 208 | peri_start_addr = 0xf0000000 209 | while idx < len(prev_fifth_mem): 210 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 211 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 212 | elif prev_fifth_mem[idx:idx+4] != next_fifth_mem[idx:idx+4]: 213 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 214 | idx = idx + 4 215 | 216 | idx=0 217 | peri_start_addr = 0xf0040000 218 | while idx < len(prev_sixth_mem): 219 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 220 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 221 | elif prev_sixth_mem[idx:idx+4] != next_sixth_mem[idx:idx+4]: 222 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 223 | idx = idx + 4 224 | 225 | fp.write("\n") 226 | fp.close() 227 | 228 | 229 | def calc_init(peri_addr): 230 | gdb.execute('mon reset 0') 231 | peri_addr = peri_addr.strip() 232 | peri_addr = int(peri_addr, 16) 233 | l = gdb.inferiors()[0] 234 | init_peri_val = l.read_memory(peri_addr, 4) 235 | init_peri_val = bytes_to_int(init_peri_val) 236 | fp = open("./result.txt", 'a') 237 | fp.write("addr 0x%x information\n" %peri_addr) 238 | fp.write("initial value 0x%x\n" %init_peri_val) 239 | fp.write("\n") 240 | 241 | def check_cache(peri_addr, value): 242 | fp = open("../result.txt", 'r') 243 | 244 | peri_addr = int(peri_addr.strip(), 16) 245 | value = int(value.strip(), 10) 246 | 247 | while True: 248 | line_1 = fp.readline() 249 | 250 | if not line_1: 251 | break 252 | 253 | addr = (line_1.split())[1] 254 | addr = int(addr, 0) 255 | 256 | line_2 = fp.readline() 257 | init_value = (line_2.split())[2] 258 | init_value = int(init_value, 0) 259 | 260 | line_3 = fp.readline() 261 | if line_3 == "\n": 262 | continue 263 | elif not line_3: 264 | break 265 | 266 | add_value = line_3.strip() 267 | add_value = int(add_value) 268 | flag = 0 269 | if addr == peri_addr and value == add_value: 270 | flag = 1 271 | output = open("./result.txt", 'a') 272 | output.write(line_1) 273 | output.write(line_2) 274 | output.write(line_3) 275 | 276 | while True: 277 | band_addr = fp.readline() 278 | if flag == 1: 279 | output.write(band_addr) 280 | 281 | if band_addr == "\n": 282 | break 283 | 284 | if flag == 1: 285 | return 1 286 | 287 | return 0 288 | 289 | def add_prev_peri(): 290 | fp = open('./peri_write.txt', 'r') 291 | l = gdb.inferiors()[0] 292 | 293 | while True: 294 | line = fp.readline() 295 | 296 | if not line: 297 | break 298 | 299 | addr = (line.split())[0] 300 | addr = int(addr, 16) 301 | 302 | line = fp.readline() 303 | add_value = (line.split())[0] 304 | add_value = int(add_value, 10) 305 | 306 | if add_value < 0: 307 | str_val = format(4294967296 - add_value, '08x') 308 | else: 309 | str_val = format(add_value, '08x') 310 | str_val = reverse(str_val) 311 | str_val = codecs.decode(str_val, "hex") 312 | l.write_memory(addr, str_val, 4) 313 | stepi(2000) 314 | 315 | fp.close() 316 | return 1 317 | 318 | def read_peri_range(): 319 | global peri_addr_range 320 | global peri_mem_map_idx 321 | 322 | fp = open('/peri_ranges', 'r') 323 | lines = fp.readlines() 324 | 325 | for line in lines: 326 | vals = line.strip().split() 327 | start_addr = int(vals[0], 16) 328 | end_addr = int(vals[1], 16) 329 | 330 | addrs = [start_addr, end_addr] 331 | peri_addr_range.append(addrs) 332 | 333 | mem_idx = [] 334 | if len(vals) > 2: 335 | idx = 2 336 | while idx < len(vals): 337 | mem_idx.append(int(vals[idx], 0)) 338 | idx += 1 339 | 340 | peri_mem_map_idx.append(mem_idx) 341 | 342 | return 343 | 344 | def main(): 345 | bin_file = "./inf.out" 346 | 347 | peri_file = "./add_regs.txt" 348 | 349 | peri_addr, value = get_peri_list(peri_file) 350 | 351 | start_gdb(bin_file) 352 | 353 | if len(value) != 0: 354 | check = check_cache(peri_addr, value) 355 | if check == 0: 356 | #read_peri_range() 357 | build_model(peri_addr, value) 358 | else: 359 | calc_init(peri_addr) 360 | 361 | 362 | if __name__ == "__main__": 363 | main() 364 | -------------------------------------------------------------------------------- /nrf52832/model/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nrfjprog --program inf.hex --sectorerase 4 | arm-none-eabi-gdb-py < add_input 5 | -------------------------------------------------------------------------------- /nrf52832/model/add_input: -------------------------------------------------------------------------------- 1 | source PeriModel.py 2 | -------------------------------------------------------------------------------- /nrf52832/model/inf.hex: -------------------------------------------------------------------------------- 1 | :1000000000000120B5020000DD020000DF02000058 2 | :10001000E1020000E3020000E50200000000000031 3 | :10002000000000000000000000000000E7020000E7 4 | :10003000E902000000000000EB020000ED020000F9 5 | :10004000EF020000EF020000EF020000EF020000EC 6 | :10005000EF020000EF020000EF020000EF020000DC 7 | :10006000EF020000EF020000EF020000EF020000CC 8 | :10007000EF020000EF020000EF020000EF020000BC 9 | :10008000EF020000EF020000EF020000EF020000AC 10 | :10009000EF020000EF020000EF020000EF0200009C 11 | :1000A000EF020000EF020000EF020000EF0200008C 12 | :1000B000EF020000EF02000000000000000000005E 13 | :1000C000EF020000EF020000EF020000EF0200006C 14 | :1000D000EF020000EF020000EF020000000000004D 15 | :1000E0000000000000000000000000000000000010 16 | :1000F0000000000000000000000000000000000000 17 | :1001000000000000000000000000000000000000EF 18 | :1001100000000000000000000000000000000000DF 19 | :1001200000000000000000000000000000000000CF 20 | :1001300000000000000000000000000000000000BF 21 | :1001400000000000000000000000000000000000AF 22 | :10015000000000000000000000000000000000009F 23 | :10016000000000000000000000000000000000008F 24 | :10017000000000000000000000000000000000007F 25 | :10018000000000000000000000000000000000006F 26 | :10019000000000000000000000000000000000005F 27 | :1001A000000000000000000000000000000000004F 28 | :1001B000000000000000000000000000000000003F 29 | :1001C000000000000000000000000000000000002F 30 | :1001D000000000000000000000000000000000001F 31 | :1001E000000000000000000000000000000000000F 32 | :1001F00000000000000000000000000000000000FF 33 | :1002000010B5054C237833B9044B13B10448AFF350 34 | :1002100000800123237010BD680000200000000052 35 | :100220009803000008B5034B1BB103490348AFF323 36 | :10023000008008BD000000006C0000209803000052 37 | :10024000154B002B08BF134B9D46A3F5803A0021A8 38 | :100250008B460F461348144A121A00F085F80F4BCC 39 | :10026000002B00D098470E4B002B00D09847002061 40 | :10027000002104000D000D48002802D00C48AFF307 41 | :10028000008000F04DF82000290000F031F800F067 42 | :1002900033F800BF0000080000000120000000004B 43 | :1002A0000000000068000020840000200000000022 44 | :1002B000000000000649074A074B9B1A03DD043B78 45 | :1002C000C858D050FBDC00F015F8FFF7B9FF00006C 46 | :1002D000A40300000000002068000020FEE7FEE705 47 | :1002E000FEE7FEE7FEE7FEE7FEE7FEE7FEE7FEE7E6 48 | :1002F000FEE700BF704700BF08B5074B044613B1C7 49 | :100300000021AFF30080054B1868836A03B198475A 50 | :10031000204600F031F800BF000000009403000008 51 | :1003200070B50D4E0D4CA41BA4100025A54209D19B 52 | :100330000B4E0C4C00F022F8A41BA4100025A54283 53 | :1003400005D170BD56F8253098470135EEE756F8CF 54 | :10035000253098470135F2E760000020600000205A 55 | :10036000600000206400002002440346934200D154 56 | :10037000704703F8011BF9E7FEE700BFF8B500BFBF 57 | :10038000F8BC08BC9E467047F8B500BFF8BC08BC76 58 | :0C0390009E4670470000002000000000A6 59 | :08039C00A4FEFF7F0100000038 60 | :1003A4000000000000000000000000000000000049 61 | :1003B4000000000000000000000000000000000039 62 | :1003C4000000000000000000000000000000000029 63 | :1003D4000000000000000000000000000000000019 64 | :1003E4000000000000000000000000000000000009 65 | :1003F40000000000000000000000000000000000F9 66 | :080404002502000001020000C6 67 | :04000003000002B542 68 | :00000001FF 69 | -------------------------------------------------------------------------------- /nrf52832/model/inf.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/nrf52832/model/inf.out -------------------------------------------------------------------------------- /nrf52832/model/peri_write.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/nrf52832/model/peri_write.txt -------------------------------------------------------------------------------- /nrf52832/result.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/nrf52832/result.txt -------------------------------------------------------------------------------- /stm32f1/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true 4 | do 5 | rm -f model/add_regs.txt 6 | ./execute_firmware.py --firmware 7 | FILE=model/add_regs.txt 8 | if [ -f "$FILE" ]; then 9 | cat $FILE 10 | cd model 11 | ./add.sh 12 | cd ../ 13 | else 14 | break 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /stm32f1/execute_firmware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | import os 5 | import sys 6 | import random 7 | from unicorn import * 8 | from unicorn.arm_const import * 9 | from capstone import * 10 | import argparse 11 | import codecs 12 | import binascii 13 | import time 14 | import os.path 15 | 16 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_MCLASS) 17 | cs = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS) 18 | 19 | peri_init = {} 20 | peri_bits = {} 21 | peri_type = {} 22 | peri_banding = {} 23 | set_bits = [] 24 | 25 | flag = 0 26 | 27 | before_value = 0 28 | before_addr = 0 29 | 30 | def arg_parser(): 31 | parser = argparse.ArgumentParser() 32 | parser.add_argument('--firmware', type=str, help="firmware binary") 33 | parser.add_argument('--base_addr', type=int, default=0x8000000, help="the base address of firmware") 34 | 35 | return parser.parse_args() 36 | 37 | def bytes_to_int(inputs): 38 | result = 0 39 | inputs = inputs[::-1] 40 | for b in inputs: 41 | result = result * 256 + int (b) 42 | 43 | return long(result) 44 | 45 | def int_to_hex_rev(value): 46 | value = int(value) 47 | hex_str = '%08x' %value 48 | str_to_convert = hex_str[6:8] + hex_str[4:6] + hex_str[2:4] + hex_str[0:2] 49 | return codecs.decode(str_to_convert, "hex") 50 | 51 | 52 | def debug_instruction(uc, address, size, user_data): 53 | global flag 54 | global global_base_addr 55 | 56 | mem = uc.mem_read(address, size) 57 | 58 | if flag == 1: 59 | flag = 0 60 | global set_bits 61 | 62 | global before_value 63 | global before_addr 64 | 65 | uc.mem_write(before_addr, int_to_hex_rev(before_value)) 66 | 67 | for addr_dict in set_bits: 68 | for addr in addr_dict: 69 | value = addr_dict[addr] 70 | prev_value = bytes_to_int(uc.mem_read(addr, 4)) 71 | new_value = value 72 | uc.mem_write(addr, int_to_hex_rev(new_value)) 73 | 74 | 75 | def mem_read(uc, access, address, size, value, data): 76 | mem_value = bytes_to_int(uc.mem_read(address, 4)) 77 | 78 | if address >= 0x40000000: 79 | if address not in peri_init: 80 | output = '%x' %address 81 | fp = open('model/add_regs.txt', 'w') 82 | fp.write(output) 83 | fp.close() 84 | os._exit(1) 85 | 86 | return 87 | return 88 | 89 | def pre_mem_write(uc, access, address, size, value, data): 90 | if address >= 0x40000000: 91 | global flag 92 | global peri_banding 93 | global set_bits 94 | 95 | flag = 1 96 | if address not in peri_init: 97 | output = '%x' %address 98 | fp = open('model/add_regs.txt', 'w') 99 | fp.write(output) 100 | fp.write("\n") 101 | fp.write(str(value)) 102 | fp.close() 103 | os._exit(1) 104 | 105 | return 106 | 107 | global before_addr 108 | global before_value 109 | before_addr = address 110 | before_value = bytes_to_int(uc.mem_read(address, 4)) 111 | if address in peri_banding: 112 | band_list = peri_banding[address] 113 | 114 | for add_dict in band_list: 115 | for add_value in add_dict: 116 | if add_value == value: 117 | write_fp = open('model/peri_write.txt', 'a') 118 | output = '%x' %address 119 | write_fp.write(output) 120 | write_fp.write("\n") 121 | write_fp.write(str(value)) 122 | write_fp.write("\n") 123 | write_fp.close() 124 | 125 | 126 | set_bits = add_dict[add_value] 127 | return 128 | 129 | 130 | output = '%x' %address 131 | fp = open('model/add_regs.txt', 'w') 132 | fp.write(output) 133 | fp.write("\n") 134 | fp.write(str(value)) 135 | fp.close() 136 | os._exit(1) 137 | 138 | return 139 | 140 | return 141 | 142 | def init_peri_reg(): 143 | global peri_init 144 | 145 | for addr in peri_init: 146 | init_value = peri_init[addr] 147 | uc.mem_write(addr, int_to_hex_rev(init_value)) 148 | return 149 | 150 | 151 | def read_peripheral_model(): 152 | global peri_init #= {} 153 | global peri_banding #= {} 154 | 155 | 156 | if (os.path.isfile('model/result.txt') == False): 157 | return 158 | 159 | fp = open('model/result.txt', 'r') 160 | 161 | while True: 162 | line = fp.readline() 163 | 164 | if not line: 165 | break 166 | 167 | addr = (line.split())[1] 168 | addr = int(addr, 0) 169 | 170 | line = fp.readline() 171 | init_value = (line.split())[2] 172 | init_value = int(init_value, 0) 173 | 174 | if addr not in peri_init: 175 | peri_init[addr] = init_value 176 | 177 | 178 | line = fp.readline() 179 | if line == "\n": 180 | continue 181 | elif not line: 182 | break 183 | 184 | add_value = line.strip() 185 | add_value = int(add_value) 186 | bit_band = [] 187 | sub_banding = {} 188 | while True: 189 | band_addr = fp.readline() 190 | if band_addr == '\n': 191 | break 192 | 193 | addr_and_value = band_addr.strip().split() 194 | band_addr = addr_and_value[0] 195 | final_val = int(addr_and_value[1]) 196 | band_addr = int(band_addr, 0) 197 | value_pair = {} 198 | value_pair[band_addr] = final_val 199 | bit_band.append(value_pair) 200 | 201 | sub_banding[add_value] = bit_band 202 | 203 | if peri_banding.has_key(addr) == True: 204 | peri_banding[addr].append(sub_banding) 205 | else: 206 | peri_banding[addr] = [] 207 | peri_banding[addr].append(sub_banding) 208 | 209 | 210 | def map_elf_memory(filename): 211 | CODE_ADDR = 0x0 212 | STACK_SIZE = 0x8000 213 | 214 | CODE = open(filename).read() 215 | 216 | fp = open(filename, 'rb') 217 | 218 | stack_addr_rev = fp.read(4) 219 | entry_addr_rev = fp.read(4) 220 | 221 | stack_addr = "" 222 | entry_addr = "" 223 | 224 | for i in range(0, len(stack_addr_rev)): 225 | stack_addr += stack_addr_rev[3-i] 226 | entry_addr += entry_addr_rev[3-i] 227 | fp.close() 228 | 229 | START_ADDR = int(entry_addr.encode("hex"), 16) 230 | STACK_ADDR = int(stack_addr.encode("hex"), 16) 231 | 232 | 233 | SIZE = 0xfffff000 234 | uc.mem_map(0x0, SIZE) 235 | uc.mem_map(0xfffff000, 0x1000) 236 | 237 | FFlist = "FF" * 0x80000 238 | FFlist = codecs.decode(FFlist, "hex") 239 | uc.mem_write(0x0, FFlist) 240 | 241 | uc.mem_write(0x8000000, CODE) 242 | uc.reg_write(UC_ARM_REG_SP, STACK_ADDR) 243 | 244 | uc.hook_add(UC_HOOK_CODE, debug_instruction) 245 | uc.hook_add(UC_HOOK_MEM_WRITE, pre_mem_write) 246 | uc.hook_add(UC_HOOK_MEM_READ, mem_read) 247 | return START_ADDR 248 | 249 | def main(): 250 | args = arg_parser() 251 | 252 | read_peripheral_model() 253 | 254 | if (os.path.isfile('model/peri_write.txt') == True): 255 | os.remove('model/peri_write.txt') 256 | fp = open('model/peri_write.txt','w') 257 | fp.close() 258 | 259 | global peri_init #= {} 260 | global peri_bits #= {} 261 | global peri_type #= [] 262 | global peri_banding #= {} 263 | global global_base_addr 264 | global_base_addr = args.base_addr 265 | start_addr = map_elf_memory(args.firmware) 266 | 267 | init_peri_reg() 268 | 269 | 270 | uc.emu_start(start_addr | 1, 0, 0, count=100000) 271 | 272 | if __name__ == "__main__": 273 | main() 274 | -------------------------------------------------------------------------------- /stm32f1/model/PeriModel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import sys 6 | import random 7 | import codecs 8 | import binascii 9 | import subprocess 10 | import time 11 | 12 | done_list = [] 13 | flag = -1 14 | 15 | peri_addr_range = [] 16 | peri_mem_map_idx = [] 17 | 18 | def arg_parser(): 19 | parser = argparse.ArgumentParser() 20 | parser.add_argument('--peri_file', type=str, default="peri_regs.txt", help="file for the list of peripheral registers address") 21 | parser.add_argument('--bin_file', type=str, help="firmware binary file name") 22 | 23 | return parser.parse_args() 24 | 25 | def read_memory(base_addr, length, filetype): 26 | if os.path.exists(filetype): 27 | os.remove(filetype) 28 | gdb.execute("set logging file " + filetype) 29 | gdb.execute("set logging on") 30 | idx = 0 31 | while (idx < length): 32 | gdb.execute("x /4x " + str(hex(base_addr + idx))) 33 | idx = idx + 16 34 | 35 | gdb.execute("set logging off") 36 | fp = open(filetype, 'r') 37 | lines = fp.readlines() 38 | result = [] 39 | for line in lines: 40 | idx = 1 41 | for j in range(0, 4): 42 | addr = line.split()[idx] 43 | addr_val = int(addr, 16) 44 | for i in range(0, 4): 45 | result.append(addr_val % 256) 46 | addr_val = addr_val / 256 47 | idx = idx + 1 48 | 49 | return result 50 | 51 | def init_read_memory(base_addr, length, filetype): 52 | if os.path.exists(filetype): 53 | os.remove(filetype) 54 | gdb.execute("set logging file " + filetype) 55 | gdb.execute("set logging on") 56 | idx = 0 57 | while (idx < length): 58 | gdb.execute("x /x " + str(hex(base_addr + idx))) 59 | idx = idx + 4 60 | 61 | gdb.execute("set logging off") 62 | fp = open(filetype, 'r') 63 | lines = fp.readlines() 64 | result = [] 65 | for line in lines: 66 | addr = line.split()[1] 67 | addr_val = int(addr, 16) 68 | for i in range(0, 4): 69 | result.append(addr_val % 256) 70 | addr_val = addr_val / 256 71 | 72 | return result 73 | 74 | 75 | def bytes_to_int(inputs): 76 | result = 0 77 | for i in range(0, 4): 78 | idx = 3 - i 79 | result = result * 256 + inputs[idx] 80 | 81 | return long(result) 82 | 83 | def get_peri_list(filename): 84 | fp = open(filename, 'r') 85 | 86 | addr = fp.readline() 87 | value = fp.readline() 88 | 89 | return addr, value 90 | 91 | def stepi(count): 92 | for i in range(count): 93 | gdb.execute('stepi') 94 | 95 | def reverse(str_val): 96 | temp = str_val[6:8] + str_val[4:6] + str_val[2:4] + str_val[0:2] 97 | return temp 98 | 99 | def start_gdb(filename): 100 | 101 | input_file = 'file ' + filename 102 | gdb.execute(input_file) 103 | gdb.execute('target remote localhost:3333') 104 | 105 | gdb.execute('mon flash probe 0') 106 | gdb.execute('mon flash protect 0 0 127 off') 107 | gdb.execute('mon reset halt') 108 | gdb.execute('load') 109 | gdb.execute('set pagination off') 110 | gdb.execute('set arm force-mode thumb') 111 | gdb.execute('set style enabled off') 112 | gdb.execute('set endian little') 113 | 114 | 115 | def build_model(peri_addr, value): 116 | l = gdb.inferiors()[0] 117 | 118 | global peri_addr_range 119 | global peri_mem_map_idx 120 | global done_list 121 | peri_addr = peri_addr.strip() 122 | peri_addr = int(peri_addr, 16) 123 | 124 | value = value.strip() 125 | value = int(value, 10) 126 | 127 | 128 | init_peri_val = init_read_memory(peri_addr, 4, "temp") 129 | init_peri_val = bytes_to_int(init_peri_val) 130 | 131 | ret = add_prev_peri() 132 | 133 | base_addr = 0x40000000 134 | length = 0x30000 135 | 136 | prev_first_mem = read_memory(base_addr, length, "temp1") 137 | prev_second_mem = read_memory(0x50000000, 0x40000, "temp2") 138 | prev_third_mem = read_memory(0xe0000000, 0x10000, "temp3") 139 | prev_fourth_mem = read_memory(0xe0040000, 0x2000, "temp4") 140 | prev_fifth_mem = read_memory(0xf0000000, 0x10000, "temp5") 141 | prev_sixth_mem = read_memory(0xf0040000, 0x2000, "temp6") 142 | 143 | if value < 0: 144 | str_val = format(4294967296 - value, '08x') 145 | else: 146 | str_val = format(value, '08x') 147 | 148 | str_val = reverse(str_val) 149 | str_val = codecs.decode(str_val, "hex") 150 | 151 | if peri_addr != 0x40010004: 152 | l.write_memory(peri_addr, str_val, 4) 153 | 154 | next_first_mem = read_memory(base_addr, length, "temp1") 155 | next_second_mem = read_memory(0x50000000, 0x40000, "temp2") 156 | next_third_mem = read_memory(0xe0000000, 0x10000, "temp3") 157 | next_fourth_mem = read_memory(0xe0040000, 0x2000, "temp4") 158 | next_fifth_mem = read_memory(0xf0000000, 0x10000, "temp5") 159 | next_sixth_mem = read_memory(0xf0040000, 0x2000, "temp6") 160 | 161 | fp = open("./result.txt", 'a') 162 | fp.write("addr 0x%x information\n" %peri_addr) 163 | fp.write("initial value 0x%x\n" %init_peri_val) 164 | fp.write("%d\n" %value) 165 | 166 | idx=0 167 | peri_start_addr = 0x40000000 168 | while idx < len(prev_first_mem): 169 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 170 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 171 | elif prev_first_mem[idx:idx+4] != next_first_mem[idx:idx+4]: 172 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 173 | idx = idx + 4 174 | 175 | idx=0 176 | peri_start_addr = 0x50000000 177 | while idx < len(prev_second_mem): 178 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 179 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 180 | elif prev_second_mem[idx:idx+4] != next_second_mem[idx:idx+4]: 181 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 182 | idx = idx + 4 183 | 184 | idx=0 185 | peri_start_addr = 0xe0000000 186 | while idx < len(prev_third_mem): 187 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 188 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 189 | elif prev_third_mem[idx:idx+4] != next_third_mem[idx:idx+4]: 190 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 191 | idx = idx + 4 192 | 193 | idx=0 194 | peri_start_addr = 0xe0040000 195 | while idx < len(prev_fourth_mem): 196 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 197 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 198 | elif prev_fourth_mem[idx:idx+4] != next_fourth_mem[idx:idx+4]: 199 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 200 | idx = idx + 4 201 | 202 | idx=0 203 | peri_start_addr = 0xf0000000 204 | while idx < len(prev_fifth_mem): 205 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 206 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 207 | elif prev_fifth_mem[idx:idx+4] != next_fifth_mem[idx:idx+4]: 208 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 209 | idx = idx + 4 210 | 211 | idx=0 212 | peri_start_addr = 0xf0040000 213 | while idx < len(prev_sixth_mem): 214 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 215 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 216 | elif prev_sixth_mem[idx:idx+4] != next_sixth_mem[idx:idx+4]: 217 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 218 | idx = idx + 4 219 | 220 | fp.write("\n") 221 | fp.close() 222 | 223 | 224 | def calc_init(peri_addr): 225 | peri_addr = peri_addr.strip() 226 | peri_addr = int(peri_addr, 16) 227 | l = gdb.inferiors()[0] 228 | init_peri_val = read_memory(peri_addr, 4, "temp") 229 | init_peri_val = bytes_to_int(init_peri_val) 230 | fp = open("./result.txt", 'a') 231 | fp.write("addr 0x%x information\n" %peri_addr) 232 | fp.write("initial value 0x%x\n" %init_peri_val) 233 | fp.write("\n") 234 | 235 | def check_cache(peri_addr, value): 236 | fp = open("../result.txt", 'r') 237 | 238 | peri_addr = int(peri_addr.strip(), 16) 239 | value = int(value.strip(), 10) 240 | 241 | while True: 242 | line_1 = fp.readline() 243 | 244 | if not line_1: 245 | break 246 | 247 | addr = (line_1.split())[1] 248 | addr = int(addr, 0) 249 | 250 | line_2 = fp.readline() 251 | init_value = (line_2.split())[2] 252 | init_value = int(init_value, 0) 253 | 254 | line_3 = fp.readline() 255 | if line_3 == "\n": 256 | continue 257 | elif not line_3: 258 | break 259 | 260 | add_value = line_3.strip() 261 | add_value = int(add_value) 262 | flag = 0 263 | if addr == peri_addr and value == add_value: 264 | flag = 1 265 | output = open("./result.txt", 'a') 266 | output.write(line_1) 267 | output.write(line_2) 268 | output.write(line_3) 269 | 270 | while True: 271 | band_addr = fp.readline() 272 | if flag == 1: 273 | output.write(band_addr) 274 | 275 | if band_addr == "\n": 276 | break 277 | 278 | if flag == 1: 279 | return 1 280 | 281 | return 0 282 | 283 | def add_prev_peri(): 284 | fp = open('./peri_write.txt', 'r') 285 | l = gdb.inferiors()[0] 286 | 287 | while True: 288 | line = fp.readline() 289 | 290 | if not line: 291 | break 292 | 293 | addr = (line.split())[0] 294 | addr = int(addr, 16) 295 | 296 | line = fp.readline() 297 | add_value = (line.split())[0] 298 | add_value = int(add_value, 10) 299 | 300 | if add_value < 0: 301 | #gdb.execute("x /4x " + str(hex(addr))) 302 | str_val = format(4294967296 - add_value, '08x') 303 | else: 304 | str_val = format(add_value, '08x') 305 | str_val = reverse(str_val) 306 | str_val = codecs.decode(str_val, "hex") 307 | 308 | if addr != 0x40010004: 309 | l.write_memory(addr, str_val, 4) 310 | #stepi(2000) 311 | #stepi(10) 312 | 313 | 314 | fp.close() 315 | return 1 316 | 317 | def read_peri_range(): 318 | global peri_addr_range 319 | global peri_mem_map_idx 320 | 321 | fp = open('/peri_ranges', 'r') 322 | lines = fp.readlines() 323 | 324 | for line in lines: 325 | vals = line.strip().split() 326 | start_addr = int(vals[0], 16) 327 | end_addr = int(vals[1], 16) 328 | 329 | addrs = [start_addr, end_addr] 330 | peri_addr_range.append(addrs) 331 | 332 | mem_idx = [] 333 | if len(vals) > 2: 334 | idx = 2 335 | while idx < len(vals): 336 | mem_idx.append(int(vals[idx], 0)) 337 | idx += 1 338 | 339 | peri_mem_map_idx.append(mem_idx) 340 | 341 | return 342 | 343 | def main(): 344 | bin_file = "program.elf" 345 | 346 | peri_file = "./add_regs.txt" 347 | 348 | peri_addr, value = get_peri_list(peri_file) 349 | 350 | start_gdb(bin_file) 351 | 352 | if len(value) != 0: 353 | check = check_cache(peri_addr, value) 354 | if check == 0: 355 | build_model(peri_addr, value) 356 | else: 357 | calc_init(peri_addr) 358 | 359 | 360 | if __name__ == "__main__": 361 | main() 362 | -------------------------------------------------------------------------------- /stm32f1/model/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | arm-none-eabi-gdb-py < add_input 4 | -------------------------------------------------------------------------------- /stm32f1/model/add_input: -------------------------------------------------------------------------------- 1 | source PeriModel.py 2 | -------------------------------------------------------------------------------- /stm32f1/model/peri_write.txt: -------------------------------------------------------------------------------- 1 | 40021000 2 | 19587 3 | -------------------------------------------------------------------------------- /stm32f1/model/program.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f1/model/program.elf -------------------------------------------------------------------------------- /stm32f1/model/result.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f1/model/result.txt -------------------------------------------------------------------------------- /stm32f1/result.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f1/result.txt -------------------------------------------------------------------------------- /stm32f4/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true 4 | do 5 | rm -f model/add_regs.txt 6 | ./execute_firmware.py --firmware 7 | FILE=model/add_regs.txt 8 | if [ -f "$FILE" ]; then 9 | cat $FILE 10 | cd model 11 | ./add.sh 12 | cd ../ 13 | else 14 | break 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /stm32f4/execute_firmware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from __future__ import print_function 4 | import os 5 | import sys 6 | import random 7 | from unicorn import * 8 | from unicorn.arm_const import * 9 | from capstone import * 10 | import argparse 11 | import codecs 12 | import binascii 13 | import time 14 | import os.path 15 | 16 | uc = Uc(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_MCLASS) 17 | cs = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS) 18 | 19 | peri_init = {} 20 | peri_banding = {} 21 | set_bits = [] 22 | 23 | flag = 0 24 | 25 | before_value = 0 26 | before_addr = 0 27 | 28 | global_base_addr = 0 29 | 30 | def arg_parser(): 31 | parser = argparse.ArgumentParser() 32 | parser.add_argument('--firmware', type=str, help="firmware binary") 33 | parser.add_argument('--base_addr', type=int, default=0x8000000, help="the base address of firmware") 34 | 35 | return parser.parse_args() 36 | 37 | def bytes_to_int(inputs): 38 | result = 0 39 | inputs = inputs[::-1] 40 | for b in inputs: 41 | result = result * 256 + int (b) 42 | 43 | return long(result) 44 | 45 | def int_to_hex_rev(value): 46 | value = int(value) 47 | hex_str = '%08x' %value 48 | str_to_convert = hex_str[6:8] + hex_str[4:6] + hex_str[2:4] + hex_str[0:2] 49 | return codecs.decode(str_to_convert, "hex") 50 | 51 | 52 | def debug_instruction(uc, address, size, user_data): 53 | global flag 54 | global global_base_addr 55 | 56 | mem = uc.mem_read(address, size) 57 | if flag == 1: 58 | flag = 0 59 | global set_bits 60 | 61 | global before_value 62 | global before_addr 63 | 64 | uc.mem_write(before_addr, int_to_hex_rev(before_value)) 65 | 66 | for addr_dict in set_bits: 67 | for addr in addr_dict: 68 | value = addr_dict[addr] 69 | prev_value = bytes_to_int(uc.mem_read(addr, 4)) 70 | new_value = value 71 | uc.mem_write(addr, int_to_hex_rev(new_value)) 72 | 73 | def mem_read(uc, access, address, size, value, data): 74 | mem_value = bytes_to_int(uc.mem_read(address, 4)) 75 | 76 | if address >= 0x40000000: 77 | if address not in peri_init: 78 | output = '%x' %address 79 | fp = open('model/add_regs.txt', 'w') 80 | fp.write(output) 81 | fp.close() 82 | os._exit(1) 83 | 84 | return 85 | return 86 | 87 | def pre_mem_write(uc, access, address, size, value, data): 88 | if address >= 0x40000000: 89 | global flag 90 | global peri_banding 91 | global set_bits 92 | 93 | flag = 1 94 | if address not in peri_init: 95 | output = '%x' %address 96 | fp = open('model/add_regs.txt', 'w') 97 | fp.write(output) 98 | fp.write("\n") 99 | fp.write(str(value)) 100 | fp.close() 101 | os._exit(1) 102 | 103 | return 104 | 105 | global before_addr 106 | global before_value 107 | before_addr = address 108 | before_value = bytes_to_int(uc.mem_read(address, 4)) 109 | if address in peri_banding: 110 | band_list = peri_banding[address] 111 | 112 | for add_dict in band_list: 113 | for add_value in add_dict: 114 | if add_value == value: 115 | write_fp = open('model/peri_write.txt', 'a') 116 | output = '%x' %address 117 | write_fp.write(output) 118 | write_fp.write("\n") 119 | write_fp.write(str(value)) 120 | write_fp.write("\n") 121 | write_fp.close() 122 | 123 | 124 | set_bits = add_dict[add_value] 125 | return 126 | 127 | 128 | output = '%x' %address 129 | fp = open('model/add_regs.txt', 'w') 130 | fp.write(output) 131 | fp.write("\n") 132 | fp.write(str(value)) 133 | fp.close() 134 | os._exit(1) 135 | 136 | return 137 | 138 | return 139 | 140 | def init_peri_reg(): 141 | global peri_init 142 | 143 | for addr in peri_init: 144 | if addr % 4 == 0: 145 | init_value = peri_init[addr] 146 | uc.mem_write(addr, int_to_hex_rev(init_value)) 147 | return 148 | 149 | 150 | def read_peripheral_model(): 151 | global peri_init #= {} 152 | global peri_banding #= {} 153 | 154 | 155 | if (os.path.isfile('model/result.txt') == False): 156 | return 157 | 158 | fp = open('model/result.txt', 'r') 159 | 160 | while True: 161 | line = fp.readline() 162 | 163 | if not line: 164 | break 165 | 166 | addr = (line.split())[1] 167 | addr = int(addr, 0) 168 | 169 | line = fp.readline() 170 | init_value = (line.split())[2] 171 | init_value = int(init_value, 0) 172 | 173 | if addr not in peri_init: 174 | peri_init[addr] = init_value 175 | 176 | 177 | line = fp.readline() 178 | if line == "\n": 179 | continue 180 | elif not line: 181 | break 182 | 183 | add_value = line.strip() 184 | add_value = int(add_value) 185 | bit_band = [] 186 | sub_banding = {} 187 | while True: 188 | band_addr = fp.readline() 189 | if band_addr == '\n': 190 | break 191 | 192 | addr_and_value = band_addr.strip().split() 193 | band_addr = addr_and_value[0] 194 | final_val = int(addr_and_value[1]) 195 | band_addr = int(band_addr, 0) 196 | value_pair = {} 197 | value_pair[band_addr] = final_val 198 | bit_band.append(value_pair) 199 | 200 | sub_banding[add_value] = bit_band 201 | 202 | if peri_banding.has_key(addr) == True: 203 | peri_banding[addr].append(sub_banding) 204 | else: 205 | peri_banding[addr] = [] 206 | peri_banding[addr].append(sub_banding) 207 | 208 | 209 | def map_elf_memory(filename): 210 | CODE_ADDR = 0x0 211 | STACK_SIZE = 0x8000 212 | 213 | CODE = open(filename).read() 214 | 215 | fp = open(filename, 'rb') 216 | 217 | stack_addr_rev = fp.read(4) 218 | entry_addr_rev = fp.read(4) 219 | 220 | stack_addr = "" 221 | entry_addr = "" 222 | 223 | for i in range(0, len(stack_addr_rev)): 224 | stack_addr += stack_addr_rev[3-i] 225 | entry_addr += entry_addr_rev[3-i] 226 | fp.close() 227 | 228 | START_ADDR = int(entry_addr.encode("hex"), 16) 229 | STACK_ADDR = int(stack_addr.encode("hex"), 16) 230 | 231 | 232 | SIZE = 0xfffff000 233 | uc.mem_map(0x0, SIZE) 234 | uc.mem_map(0xfffff000, 0x1000) 235 | 236 | FFlist = "FF" * 0x80000 237 | FFlist = codecs.decode(FFlist, "hex") 238 | uc.mem_write(0x0, FFlist) 239 | 240 | uc.mem_write(0x8000000, CODE) 241 | uc.reg_write(UC_ARM_REG_SP, STACK_ADDR) 242 | 243 | uc.hook_add(UC_HOOK_CODE, debug_instruction) 244 | uc.hook_add(UC_HOOK_MEM_WRITE, pre_mem_write) 245 | uc.hook_add(UC_HOOK_MEM_READ, mem_read) 246 | return START_ADDR 247 | 248 | def main(): 249 | args = arg_parser() 250 | 251 | read_peripheral_model() 252 | 253 | if (os.path.isfile('model/peri_write.txt') == True): 254 | os.remove('model/peri_write.txt') 255 | fp = open('model/peri_write.txt','w') 256 | fp.close() 257 | 258 | global peri_init #= {} 259 | global peri_banding #= {} 260 | global global_base_addr 261 | global_base_addr = args.base_addr 262 | start_addr = map_elf_memory(args.firmware) 263 | 264 | init_peri_reg() 265 | 266 | 267 | uc.emu_start(start_addr | 1, 0, 0, count=100000) 268 | 269 | if __name__ == "__main__": 270 | main() 271 | -------------------------------------------------------------------------------- /stm32f4/model/PeriModel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import sys 6 | import random 7 | import codecs 8 | import binascii 9 | import subprocess 10 | import time 11 | 12 | flag = -1 13 | 14 | peri_addr_range = [] 15 | peri_mem_map_idx = [] 16 | 17 | def arg_parser(): 18 | parser = argparse.ArgumentParser() 19 | parser.add_argument('--peri_file', type=str, default="peri_regs.txt", help="file for the list of peripheral registers address") 20 | parser.add_argument('--bin_file', type=str, help="firmware binary file name") 21 | 22 | return parser.parse_args() 23 | 24 | def read_memory(base_addr, length, filetype): 25 | if os.path.exists(filetype): 26 | os.remove(filetype) 27 | gdb.execute("set logging file " + filetype) 28 | gdb.execute("set logging on") 29 | idx = 0 30 | while (idx < length): 31 | gdb.execute("x /4x " + str(hex(base_addr + idx))) 32 | idx = idx + 16 33 | 34 | gdb.execute("set logging off") 35 | fp = open(filetype, 'r') 36 | lines = fp.readlines() 37 | result = [] 38 | for line in lines: 39 | idx = 1 40 | for j in range(0, 4): 41 | addr = line.split()[idx] 42 | addr_val = int(addr, 16) 43 | for i in range(0, 4): 44 | result.append(addr_val % 256) 45 | addr_val = addr_val / 256 46 | idx = idx + 1 47 | return result 48 | 49 | def init_read_memory(base_addr, length, filetype): 50 | if os.path.exists(filetype): 51 | os.remove(filetype) 52 | gdb.execute("set logging file " + filetype) 53 | gdb.execute("set logging on") 54 | idx = 0 55 | while (idx < length): 56 | gdb.execute("x /x " + str(hex(base_addr + idx))) 57 | idx = idx + 4 58 | 59 | gdb.execute("set logging off") 60 | fp = open(filetype, 'r') 61 | lines = fp.readlines() 62 | result = [] 63 | for line in lines: 64 | addr = line.split()[1] 65 | addr_val = int(addr, 16) 66 | for i in range(0, 4): 67 | result.append(addr_val % 256) 68 | addr_val = addr_val / 256 69 | 70 | return result 71 | 72 | 73 | def bytes_to_int(inputs): 74 | result = 0 75 | 76 | for i in range(0, 4): 77 | idx = 3 - i 78 | result = result * 256 + inputs[idx] 79 | 80 | return long(result) 81 | 82 | def get_peri_list(filename): 83 | fp = open(filename, 'r') 84 | 85 | addr = fp.readline() 86 | value = fp.readline() 87 | 88 | return addr, value 89 | 90 | def stepi(count): 91 | for i in range(count): 92 | gdb.execute('stepi') 93 | 94 | def reverse(str_val): 95 | temp = str_val[6:8] + str_val[4:6] + str_val[2:4] + str_val[0:2] 96 | return temp 97 | 98 | def start_gdb(filename): 99 | 100 | input_file = 'file ' + filename 101 | gdb.execute(input_file) 102 | gdb.execute('target remote localhost:3333') 103 | 104 | gdb.execute('mon flash probe 0') 105 | gdb.execute('mon flash protect 0 0 127 off') 106 | gdb.execute('mon reset halt') 107 | gdb.execute('load') 108 | gdb.execute('set pagination off') 109 | gdb.execute('set arm force-mode thumb') 110 | gdb.execute('set style enabled off') 111 | gdb.execute('set endian little') 112 | 113 | 114 | def build_model(peri_addr, value): 115 | 116 | l = gdb.inferiors()[0] 117 | 118 | global peri_addr_range 119 | global peri_mem_map_idx 120 | peri_addr = peri_addr.strip() 121 | peri_addr = int(peri_addr, 16) 122 | 123 | value = value.strip() 124 | value = int(value, 10) 125 | 126 | init_peri_val = init_read_memory(peri_addr, 4, "temp") 127 | init_peri_val = bytes_to_int(init_peri_val) 128 | 129 | ret = add_prev_peri() 130 | 131 | base_addr = 0x40000000 132 | length = 0x30000 133 | 134 | prev_first_mem = read_memory(base_addr, length, "temp1") 135 | prev_second_mem = read_memory(0x50000000, 0x40000, "temp2") 136 | prev_third_mem = read_memory(0xe0000000, 0x10000, "temp3") 137 | prev_fourth_mem = read_memory(0xe0040000, 0x2000, "temp4") 138 | prev_fifth_mem = read_memory(0xf0000000, 0x10000, "temp5") 139 | prev_sixth_mem = read_memory(0xf0040000, 0x2000, "temp6") 140 | 141 | if peri_addr != 0x40023c10 and peri_addr != 0x40023c04 and peri_addr != 0xffffffff: 142 | if peri_addr % 0x4 == 0: 143 | if value < 0: 144 | str_val = format(4294967296 - value, '08x') 145 | else: 146 | str_val = format(value, '08x') 147 | str_val = reverse(str_val) 148 | str_val = codecs.decode(str_val, "hex") 149 | 150 | l.write_memory(peri_addr, str_val, 4) 151 | else: 152 | str_val = format(1 << 8*(peri_addr % 4), '08x') 153 | str_val = reverse(str_val) 154 | str_val = codecs.decode(str_val, "hex") 155 | 156 | l.write_memory(int(peri_addr/4)*4, str_val, 4) 157 | 158 | #stepi(2000) 159 | 160 | next_first_mem = read_memory(base_addr, length, "temp1") 161 | next_second_mem = read_memory(0x50000000, 0x40000, "temp2") 162 | next_third_mem = read_memory(0xe0000000, 0x10000, "temp3") 163 | next_fourth_mem = read_memory(0xe0040000, 0x2000, "temp4") 164 | next_fifth_mem = read_memory(0xf0000000, 0x10000, "temp5") 165 | next_sixth_mem = read_memory(0xf0040000, 0x2000, "temp6") 166 | 167 | fp = open("./result.txt", 'a') 168 | fp.write("addr 0x%x information\n" %peri_addr) 169 | fp.write("initial value 0x%x\n" %init_peri_val) 170 | fp.write("%d\n" %value) 171 | 172 | idx=0 173 | peri_start_addr = 0x40000000 174 | while idx < len(prev_first_mem): 175 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 176 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 177 | elif prev_first_mem[idx:idx+4] != next_first_mem[idx:idx+4]: 178 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_first_mem[idx:idx+4]))) 179 | idx = idx + 4 180 | 181 | idx=0 182 | peri_start_addr = 0x50000000 183 | while idx < len(prev_second_mem): 184 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 185 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 186 | elif prev_second_mem[idx:idx+4] != next_second_mem[idx:idx+4]: 187 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_second_mem[idx:idx+4]))) 188 | idx = idx + 4 189 | 190 | idx=0 191 | peri_start_addr = 0xe0000000 192 | while idx < len(prev_third_mem): 193 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 194 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 195 | elif prev_third_mem[idx:idx+4] != next_third_mem[idx:idx+4]: 196 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_third_mem[idx:idx+4]))) 197 | idx = idx + 4 198 | 199 | idx=0 200 | peri_start_addr = 0xe0040000 201 | while idx < len(prev_fourth_mem): 202 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 203 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 204 | elif prev_fourth_mem[idx:idx+4] != next_fourth_mem[idx:idx+4]: 205 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fourth_mem[idx:idx+4]))) 206 | idx = idx + 4 207 | 208 | idx=0 209 | peri_start_addr = 0xf0000000 210 | while idx < len(prev_fifth_mem): 211 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 212 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 213 | elif prev_fifth_mem[idx:idx+4] != next_fifth_mem[idx:idx+4]: 214 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_fifth_mem[idx:idx+4]))) 215 | idx = idx + 4 216 | 217 | idx=0 218 | peri_start_addr = 0xf0040000 219 | while idx < len(prev_sixth_mem): 220 | if idx + peri_start_addr >= peri_addr and idx + peri_start_addr <= peri_addr + 3: 221 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 222 | elif prev_sixth_mem[idx:idx+4] != next_sixth_mem[idx:idx+4]: 223 | fp.write("0x%x %d\n" %(idx + peri_start_addr, bytes_to_int(next_sixth_mem[idx:idx+4]))) 224 | idx = idx + 4 225 | 226 | fp.write("\n") 227 | fp.close() 228 | 229 | 230 | def calc_init(peri_addr): 231 | peri_addr = peri_addr.strip() 232 | peri_addr = int(peri_addr, 16) 233 | l = gdb.inferiors()[0] 234 | init_peri_val = read_memory(peri_addr, 4, "temp") 235 | init_peri_val = bytes_to_int(init_peri_val) 236 | fp = open("./result.txt", 'a') 237 | fp.write("addr 0x%x information\n" %peri_addr) 238 | fp.write("initial value 0x%x\n" %init_peri_val) 239 | fp.write("\n") 240 | 241 | def check_cache(peri_addr, value): 242 | fp = open("../result.txt", 'r') 243 | 244 | peri_addr = int(peri_addr.strip(), 16) 245 | value = int(value.strip(), 10) 246 | 247 | while True: 248 | line_1 = fp.readline() 249 | 250 | if not line_1: 251 | break 252 | 253 | addr = (line_1.split())[1] 254 | addr = int(addr, 0) 255 | 256 | line_2 = fp.readline() 257 | init_value = (line_2.split())[2] 258 | init_value = int(init_value, 0) 259 | 260 | line_3 = fp.readline() 261 | if line_3 == "\n": 262 | continue 263 | elif not line_3: 264 | break 265 | 266 | add_value = line_3.strip() 267 | add_value = int(add_value) 268 | flag = 0 269 | if addr == peri_addr and value == add_value: 270 | flag = 1 271 | output = open("./result.txt", 'a') 272 | output.write(line_1) 273 | output.write(line_2) 274 | output.write(line_3) 275 | 276 | while True: 277 | band_addr = fp.readline() 278 | if flag == 1: 279 | output.write(band_addr) 280 | 281 | if band_addr == "\n": 282 | break 283 | 284 | if flag == 1: 285 | return 1 286 | 287 | return 0 288 | 289 | def add_prev_peri(): 290 | fp = open('./peri_write.txt', 'r') 291 | l = gdb.inferiors()[0] 292 | 293 | while True: 294 | line = fp.readline() 295 | 296 | if not line: 297 | break 298 | 299 | addr = (line.split())[0] 300 | addr = int(addr, 16) 301 | 302 | line = fp.readline() 303 | add_value = (line.split())[0] 304 | add_value = int(add_value, 10) 305 | 306 | if addr != 0x40023c10 and addr != 0x40023c04 and addr != 0xffffffff: 307 | if addr % 4 == 0: 308 | if add_value < 0: 309 | str_val = format(4294967296 - add_value, '08x') 310 | else: 311 | str_val = format(add_value, '08x') 312 | str_val = reverse(str_val) 313 | str_val = codecs.decode(str_val, "hex") 314 | l.write_memory(addr, str_val, 4) 315 | else: 316 | str_val = format(add_value << 8*(addr % 4), '08x') 317 | str_val = reverse(str_val) 318 | str_val = codecs.decode(str_val, "hex") 319 | l.write_memory(int(addr/4)*4, str_val, 4) 320 | 321 | #stepi(2000) 322 | #stepi(10) 323 | 324 | fp.close() 325 | return 1 326 | 327 | def read_peri_range(): 328 | global peri_addr_range 329 | global peri_mem_map_idx 330 | 331 | fp = open('/peri_ranges', 'r') 332 | lines = fp.readlines() 333 | 334 | for line in lines: 335 | vals = line.strip().split() 336 | start_addr = int(vals[0], 16) 337 | end_addr = int(vals[1], 16) 338 | 339 | addrs = [start_addr, end_addr] 340 | peri_addr_range.append(addrs) 341 | 342 | mem_idx = [] 343 | if len(vals) > 2: 344 | idx = 2 345 | while idx < len(vals): 346 | mem_idx.append(int(vals[idx], 0)) 347 | idx += 1 348 | 349 | peri_mem_map_idx.append(mem_idx) 350 | 351 | return 352 | 353 | def main(): 354 | bin_file = "program.elf" 355 | 356 | peri_file = "./add_regs.txt" 357 | 358 | peri_addr, value = get_peri_list(peri_file) 359 | 360 | start_gdb(bin_file) 361 | 362 | if len(value) != 0: 363 | check = check_cache(peri_addr, value) 364 | if check == 0: 365 | build_model(peri_addr, value) 366 | else: 367 | calc_init(peri_addr) 368 | 369 | 370 | if __name__ == "__main__": 371 | main() 372 | -------------------------------------------------------------------------------- /stm32f4/model/add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | arm-none-eabi-gdb-py < add_input 4 | -------------------------------------------------------------------------------- /stm32f4/model/add_input: -------------------------------------------------------------------------------- 1 | source PeriModel.py 2 | -------------------------------------------------------------------------------- /stm32f4/model/peri_write.txt: -------------------------------------------------------------------------------- 1 | 40023800 2 | 24707 3 | 40023808 4 | 0 5 | 40023800 6 | 24707 7 | 40023804 8 | 603992080 9 | 40023800 10 | 24707 11 | 4002380c 12 | 0 13 | e000ed08 14 | 134217728 15 | 40023c00 16 | 512 17 | 40023c00 18 | 1536 19 | 40023c00 20 | 1792 21 | -------------------------------------------------------------------------------- /stm32f4/model/program.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f4/model/program.elf -------------------------------------------------------------------------------- /stm32f4/model/result.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f4/model/result.txt -------------------------------------------------------------------------------- /stm32f4/result.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OSUSecLab/AutoMap/c33647e0344a909a8904ccc71a6a4c3b85fd38a4/stm32f4/result.txt --------------------------------------------------------------------------------