前言
结合书《CTF特训营》IoT篇看最佳
0x01 静态分析
指定处理器类型为ARM little-endian,不然
正常打开之后先看看DCD部分
DCD:数据定义( Data Definition )伪指令 一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。
语法格式:
标号 DCD(或 DCDU) 表达式
DCD(或 DCDU)伪指令用于分配一片连续的字存储单元并用指定的表达式初始化。其中表达式可以为程序标号或数字表达式。 DCD 也可用 “ &” 代替。
用 DCD 分配的字存储单元是字对齐的,而用 DCDU 分配的字存储单元并不严格字对齐。
实例(STM32 启动文件):
__Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler
所以第二个即为Reset handler,即0x8000101
The reset handler contains program code that is executed as soon as the processor exits from reset. In some cases, it contains some hardware initialization.
实际地址为0x8000100
These vectors have LSB set to 1 to indicate that the exceptions handlers are to be executed with Thumb instructions
另一种判断指令集为thumb的方法
这有一段指令,判断出目前是thumb指令集的
![mark](PCTF2016:Confused ARM 调试记录/bDfa164Gm2.png)
(图来自sakura博客,与confused arm无关)
- Edit->segments->change segment register value(快捷键ALT+G)
按下ALT+G,T的value 为0x0,就是指定为ARM指令集,设定为0x1,就是thumb指令集
然后在0x8000100
处按C转换成code
然后我们跟随0x8000100
这个程序入口开始,一路跳转到0x8001084
多选然后转换成hex
0x40000000
和0x20000000
,前者是特殊功能寄存器的基地址,后者是sram的起始地址
将这些地址添加为segment,在Edit->Segments->Create segemt
SRAM部分同上,
然后在汇编中对这地址按O
然后在伪代码中再按一次F5刷新
随后在这些疑似数组的地方用如下方式进行转换
void __fastcall __noreturn sub_8001084(int a1)
{
int v1; // r0
int v2; // r0
v1 = sub_8000A00(a1);
v2 = sub_80006A4(v1);
sub_80007F0(v2);
sub_8000A50(0x1C200);
sub_8000AA8(&USART1, 0x40);
sub_8000560(byte_2000000C, &unk_2000026C);
while ( 1 )
{
if ( unk_20000000 )
{
sub_8000BA4(
"Key is :0x%08x,0x%08x,0x%08x,0x%08x\r\n",
byte_2000000C[0],
byte_2000000C[1],
byte_2000000C[2],
byte_2000000C[3]);
unk_20000000 = 0;
}
if ( !sub_80007E2(1073809408, 2) )
{
sub_800055C(byte_2000000C, &unk_2000026C);
sub_8000248(&unk_2000001C, byte_2000031C);
sub_8000AA8(&USART1, 64);
sub_8000BA4(
"Fl4g 1s :PCTF{%08x%08x%08x%08x}\r\n",
byte_2000031C[0],
byte_2000031C[1],
byte_2000031C[2],
byte_2000031C[3]);
}
}
}
0x02 动态调试
参考书459页进行配置
如果load hex之后提示no write permission,请按照462页的工程设置界面,将最下面的CPU DLL, Driver DLl, Dialog DLL和Parameter对照一致设置好就行
按照书上改名过后
资料可参考这儿
==打patch为0C 4A,改成0B 4A 理解不能QwQ,后面的打patch也理解不能QwQ==
改checksum,可用以下脚本计算,来源
def check(DD):
length=len(DD) #求长度
#创建一个list,将传入的str的每两个数合在一起,再求和
list1=[]
if(length%2==1): #如果str长度为单数,则抛出错误
print('[!] 数据长度有误')
else:
for i in range(0, length, 2): #range(开始,结束-1,每次加多少) 这里即0——length-1 每次循环i+2
hex_digit=DD[i:i + 2] #将传入的str的每两个数合在一起
list1.append('0x'+hex_digit) #再每个字符前+0x 但是它仍然是字符,但更便于下面通过int(list1[i], 16)转换成16进制
print(list1)
sum=0
for i in range(int(length/2)): #求和
sum=int(list1[i], 16)+sum #int(list1[i], 16)将16进制转换成10进制 int类型
sum=sum%256
sum=256-sum
print('校验码: '+hex(sum)) #将sum和结果转换成16进制 hex(sum)
if __name__=="__main__":
DD=input("请输入HEX文件数据记录(校验值除外):") #input接收参数为str类型
check(DD)
然后MDK里reload之后,run就可以了
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付