这周打了两个比赛,个人感觉 b01lers CTF 偏简单一些,WolvCTF 比前者难一点。
养生型选手,一共做了三个题
b01lers CTF
Safe
一个嵌入式逆向的题目,是逆向 Arduino UNO
一个门锁一样的东西。附件给了固件,效果图,和电路原理图。
直接把给的固件拖到 ghidra
,因为固件是Intel Hex 格式的并不包含架构信息所以需要我们手动选择一下,这里选择 AVR8 gcc
(Arduino UNO
所采用的芯片使用的架构是 AVR8),首先找到入口函数,发现有 Reset
函数如下图
所以,被我重命名成 reset_impl
的函数应该就是入口了。
void reset_impl(void)
{
undefined1 *puVar1;
R1 = 0;
SREG = 0;
Ylo = 0xff;
Yhi = 8;
R17 = '\x01';
X = &mem_100;
Z = &DAT_codebyte_0582;
while (puVar1 = X, (byte)X != 0x1c || X._1_1_ != (char)(R17 + ((byte)X < 0x1c))) {
R0 = *Z;
Z = Z + 1;
X = X + 1;
*puVar1 = R0;
}
R18 = '\x01';
X = &DAT_mem_011c;
while (puVar1 = X, (byte)X != 0x3a || X._1_1_ != (char)(R18 + ((byte)X < 0x3a))) {
X = X + 1;
*puVar1 = R1;
}
mem_const_7c = 0x7c;
real_main();
while_true();
return;
}
显然就是设置了一堆内存信息,然后调用了两个函数,重点关注被我重命名为 real_main
的函数,while_true 那个就是一个空的死循环,在嵌入式中很常见。
后面了解了一下
Arduino
开发,这个 real_main 函数应该就是 setup 函数
real_main
的实现就比较复杂了,我在参考 Arduino
的标准库源码之后基本还原了所有用到的函数的符号,具体实现如下
void real_main(void)
{
char cVar1;
char *pcVar2;
byte *pbVar3;
char *pcVar4;
// 初始化一堆寄存器
R1 = 0;
R25R24._0_1_ = TCNT2;
R25R24._0_1_ = (byte)R25R24 | 2;
TCNT2 = (byte)R25R24;
R25R24._0_1_ = TCNT2;
R25R24._0_1_ = (byte)R25R24 | 1;
TCNT2 = (byte)R25R24;
R25R24._0_1_ = TCCR2;
R25R24._0_1_ = (byte)R25R24 | 2;
TCCR2 = (byte)R25R24;
R25R24._0_1_ = TCCR2;
R25R24._0_1_ = (byte)R25R24 | 1;
TCCR2 = (byte)R25R24;
R25R24._0_1_ = DAT_mem_006e;
R25R24._0_1_ = (byte)R25R24 | 1;
DAT_mem_006e = (byte)R25R24;
ICR3H = 0;
R25R24._0_1_ = ICR3H;
R25R24._0_1_ = (byte)R25R24 | 2;
ICR3H = (byte)R25R24;
R25R24._0_1_ = ICR3H;
R25R24._0_1_ = (byte)R25R24 | 1;
ICR3H = (byte)R25R24;
R25R24._0_1_ = ICR3L;
R25R24._0_1_ = (byte)R25R24 | 1;
ICR3L = (byte)R25R24;
R25R24._0_1_ = DAT_mem_00b1;
R25R24._0_1_ = (byte)R25R24 | 4;
DAT_mem_00b1 = (byte)R25R24;
R25R24._0_1_ = DAT_mem_00b0;
R25R24._0_1_ = (byte)R25R24 | 1;
DAT_mem_00b0 = (byte)R25R24;
R25R24._0_1_ = TCCR1C;
R25R24._0_1_ = (byte)R25R24 | 4;
TCCR1C = (byte)R25R24;
R25R24._0_1_ = TCCR1C;
R25R24._0_1_ = (byte)R25R24 | 2;
TCCR1C = (byte)R25R24;
R25R24._0_1_ = TCCR1C;
R25R24._0_1_ = (byte)R25R24 | 1;
TCCR1C = (byte)R25R24;
R25R24._0_1_ = TCCR1C;
R25R24._0_1_ = (byte)R25R24 | 0x80;
TCCR1C = (byte)R25R24;
DAT_mem_00c1 = 0;
// 设置引脚模式
pinMode(10,1);
R25R24 = CONCAT11(R25R24._1_1_,11);
pinMode(11,1);
R15R14 = &DAT_mem_0118;
Y = &DAT_mem_0114;
do {
pbVar3 = Y;
Y = Y + 1;
R25R24._0_1_ = *pbVar3;
R25R24 = R25R24 & 0xff00 | (uint)(byte)R25R24;
/* pinMode(R24, INPUT_PULLUP) */
pinMode((byte)R25R24,2);
Z = R15R14 + 1;
R17R16._1_1_ = *R15R14;
R17R16 = (byte *)((uint)R17R16 & 0xff | (uint)R17R16._1_1_ << 8);
R15R14 = Z;
R25R24 = R25R24 & 0xff00 | (uint)R17R16._1_1_;
pinMode(R17R16._1_1_,1);
R25R24 = R25R24 & 0xff00 | (uint)R17R16 >> 8;
R25R24._0_1_ = (byte)((uint)R17R16 >> 8);
digitalWrite((byte)R25R24,'\x01');
Z = (byte *)CONCAT11(1,(byte)Z);
} while ((byte)Y != 0x18 || Y._1_1_ != (char)(((byte)Y < 0x18) + '\x01'));
R10 = '9';
R11 = 1;
R17R16 = &DAT_mem_0125;
R7 = 20;
R8 = 0;
R9 = '\0';
LAB_code_0242:
R25R24 = 0x100;
// 扫描按键
/* 5 4 3 2 */
R15R14 = &DAT_mem_0118;
Y._0_1_ = 0;
do {
Z = R15R14 + 1;
R6 = *R15R14;
R15R14 = Z;
R25R24 = R25R24 & 0xff00 | (uint)R6;
digitalWrite(R6,0);
/* 9 8 7 6 */
R13R12 = &DAT_mem_0114;
Y._1_1_ = 0;
do {
Z = R13R12 + 1;
R5 = *R13R12;
R13R12 = Z;
R25R24 = digitalRead(R5);
R25R24._0_1_ = (byte)R25R24 | R25R24._1_1_;
R25R24 = R25R24 & 0xff00;
if ((byte)R25R24 == 0) {
do {
R25R24 = digitalRead(R5);
R25R24._0_1_ = (byte)R25R24 | R25R24._1_1_;
} while ((byte)R25R24 == 0);
Z = (byte *)CONCAT11(-((DAT_mem_0139 < 0xdb) + -2),DAT_mem_0139 + 0x25);
R25R24._0_1_ = DAT_mem_0139;
*Z = Y._1_1_ + (byte)Y;
DAT_mem_0139 = (byte)R25R24 + 1;
R25R24 = FUN_code_0156(0,0x32);
}
Y._1_1_ = Y._1_1_ + 1;
} while (Y._1_1_ != 4);
R25R24 = R25R24 & 0xff00 | (uint)R6;
digitalWrite(R6,0x1);
Y._0_1_ = (byte)Y + 0x4;
} while ((byte)Y != 16);
// 判断长度,等于20就对比
if (DAT_mem_0139 == 20) {
Z = &DAT_mem_0125;
X = &mem_100; // [0x0d, 0x05, 0x0f, 0x04, 0x0c, 0x00, 0x09, 0x07, 0x0d, 0x07, 0x09, 0x04, 0x05, 0x08, 0x06, 0x0d, 0x0e, 0x05, 0x05, 0x0f] maybe
LAB_code_0284:
pcVar4 = (char *)Z;
pcVar2 = X;
Z = (byte *)((char *)Z + 1);
R25R24._1_1_ = *pcVar4;
X = X + 1;
R25R24._0_1_ = *pcVar2;
if (R25R24._1_1_ == (byte)R25R24) goto LAB_code_02ad;
cVar1 = 5;
do {
R25R24 = CONCAT11(R25R24._1_1_,11);
digitalWrite(11,1);
FUN_code_0156(0,0xf4);
R25R24 = CONCAT11(R25R24._1_1_,11);
digitalWrite(11,0);
R25R24._1_1_ = 0;
FUN_code_0156(0,0xf4);
cVar1 = cVar1 + -1;
} while (cVar1 != 0);
goto LAB_code_029f;
}
goto LAB_code_02a6;
LAB_code_02ad:
if (R10 == (byte)Z && R11 == (char)(Z._1_1_ + (R10 < (byte)Z))) goto code_c0x02b0;
goto LAB_code_0284;
code_c0x02b0: // 应该是开
标签:b01lers,WriteUp,Re,flag,._,R25R24,ARRAY,null,byte
From: https://www.cnblogs.com/gaoyucan/p/17237028.html