Konu Başlıkları Gizle
1. Dosya Adı ve Komut Kontrolü (FUN_00004538)
Bu fonksiyon, bootloader'ın kabul ettiği dosya isimlerini veya komutları belirleyen "bekçi" fonksiyonudur.- Analiz: Fonksiyon, kullanıcıdan gelen girdiyi (muhtemelen yüklenen dosyanın adı veya POST isteğindeki bir parametre) hafızadaki sabit dize (string) listesiyle karşılaştırır.
- Bulgu: Kodda bir do-while döngüsü ile giriş dizisi,
DAT_81fd0b9c,DAT_81fd0ba8gibi adreslerdeki dizilerle kıyaslanıyor. Eşleşme durumuna göre_DAT_81fd6484değişkenine 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 5, 6 gibi değerler atanıyor. - Anlamı:Bootloader sadece belirli dosya isimlerini kabul edecek şekilde programlanmıştır.
- Genellikle 1 numaralı durum tclinux.bin (Standart Firmware) içindir.
- 2 numaralı durum genellikle romfile.cfg (Konfigürasyon) içindir.
- Diğer durumlar (tcboot.bin vb.) bootloader güncellemesi veya özel modlar içindir.
- Öneri: Yüklemeye çalıştığınız dosyanın adını tclinux.bin olarak değiştirin. Web arayüzü genellikle sadece bu ismi veya romfile.cfg ismini kabul eder.
C:
/* WARNING: Control flow encountered bad instruction data */
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
undefined4 FUN_00004538(int param_1)
{
bool bVar1;
char cVar2;
char cVar3;
char *pcVar4;
char cVar5;
char *pcVar6;
int iVar7;
char *pcVar8;
_DAT_81fd5a88 = func_0x01fb39f4();
_DAT_81fd5a8c = func_0x01fb3d08(param_1);
pcVar6 = &DAT_81fd6488;
pcVar4 = (char *)(*(int *)(param_1 + 0x7d4) + 2);
iVar7 = 0x7f;
pcVar8 = pcVar6;
do {
cVar2 = *pcVar4;
iVar7 = iVar7 + -1;
*pcVar8 = cVar2;
pcVar8 = pcVar8 + 1;
if (cVar2 == '\0') break;
pcVar4 = pcVar4 + 1;
} while (iVar7 != 0);
pcVar8 = &DAT_81fd0b9c;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar6 = pcVar6 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar6;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 1;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd0ba8;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 2;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd1988;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 3;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd1998;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 4;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19a8;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 7;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19b8;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 8;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19c8;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 9;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19d4;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 10;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19e0;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 0xb;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19ec;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 0xc;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd19fc;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 == cVar3) {
_DAT_81fd6484 = 5;
}
else {
pcVar4 = &DAT_81fd6488;
pcVar8 = &DAT_81fd1a08;
cVar2 = DAT_81fd6488;
do {
cVar3 = *pcVar8;
pcVar4 = pcVar4 + 1;
pcVar8 = pcVar8 + 1;
cVar5 = cVar2;
if (cVar3 != cVar2) break;
bVar1 = cVar2 != '\0';
cVar2 = *pcVar4;
cVar5 = cVar3;
} while (bVar1);
if (cVar5 != cVar3) {
_DAT_81fd6484 = 0xffff;
func_0x01fb4120(*(undefined4 *)(param_1 + 0x7d4),0);
_DAT_81fd5a84 = 1;
func_0x01fb4ae0();
return 0;
}
_DAT_81fd6484 = 6;
}
}
}
}
}
}
}
}
}
}
}
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
2. Sihirli Bayt (Magic Bytes) Kontrolü (FUN_00001e1c ve FUN_00003bc8)
Bootloader, yüklenen dosyanın geçerli bir TrendChip firmware'i olup olmadığını başındaki "sihirli sayılara" bakarak anlar.- Magic Value:
FUN_00001e1cfonksiyonunda0x54321253değeri kontrol ediliyor.- Bu değer ASCII olarak T2.S (veya endian durumuna göre benzer bir varyasyon) anlamına gelebilir.
- Ayrıca
FUN_00003bc8fonksiyonunda dosyanın belirli bir ofsetinde (muhtemelen header'ın 2. baytı) 0x45 değeri aranıyor.
- Öneri: Yüklemeye çalıştığınız
mtd6_backup.bindosyasının bir Hex Editör ile ilk 4-8 baytını kontrol edin. Eğer bu 0x54321253 (veya 53 12 32 54) imzasını taşımıyorsa, bootloader dosyayı "bozuk" olarak işaretleyip reddedecektir. Orijinal bir tclinux.bin dosyasının başlık kısmını (ilk 256 bayt) kendi dosyanızın başına eklemeyi (header transplantation) deneyebilirsiniz.
C:
/* WARNING: Control flow encountered bad instruction data */
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
undefined4 FUN_00001e1c(undefined4 param_1,int param_2)
{
int iVar1;
int *piVar2;
undefined4 uVar3;
int iVar4;
undefined1 auStack_30 [4];
int local_2c;
int local_28;
int local_24;
int local_20;
iVar1 = func_0x01fb7334(*(undefined4 *)(param_2 + 4),0,0x10);
piVar2 = (int *)func_0x01fb7334(*(undefined4 *)(param_2 + 8),0,0x10);
if ((((((_DAT_bfb00064 & 0xffff0000) == 0x70000) || ((_DAT_bfb00064 & 0xffff0000) == 0x30000)) ||
((_DAT_bfb00064 & 0xffff0000) == 0x40000)) || ((_DAT_bfb00064 & 0xffff0000) == 0x50000)) &&
((_DAT_bfa10114 & 2) != 0)) {
func_0x01fb8cbc(0x81fd0d50);
}
else {
if (*piVar2 == 0x54321253) {
local_28 = piVar2[1];
local_24 = iVar1 + piVar2[1];
local_20 = piVar2[2];
local_2c = iVar1;
func_0x01fb8cbc(0x81fd0d7c,iVar1,local_28,local_24,local_20);
iVar4 = local_20 + local_28;
func_0x01fb8cbc(0x81fd0afc,piVar2 + 8,iVar1,iVar4);
func_0x01fb9f00(iVar1,iVar4);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(iVar1,iVar4,auStack_30,piVar2 + 8);
uVar3 = func_0x01fbe768();
func_0x01fb9e20(0,uVar3,auStack_30,0x80020000);
_DAT_8002fef0 = local_2c;
_DAT_8002fef4 = local_28;
_DAT_8002fef8 = local_24;
_DAT_8002fefc = local_20;
uVar3 = func_0x01fbe768();
func_0x01fb9f00(0,uVar3);
func_0x01fb8cbc(0x81fd4070);
uVar3 = func_0x01fbe768();
func_0x01fb9d40(0,uVar3,auStack_30,0x80020000);
return 0;
}
func_0x01fb8cbc(0x81fd0f98);
}
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
C:
/* WARNING: Control flow encountered bad instruction data */
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
undefined4 FUN_00003bc8(int param_1)
{
ushort *puVar1;
char cVar2;
int *piVar3;
undefined4 uVar4;
int iVar5;
int *piVar6;
iVar5 = *(int *)(param_1 + 0x7d4);
*(int *)(param_1 + 0x7d8) = iVar5;
if (*(int *)(iVar5 + 0x10) != _DAT_81fd6460) {
return 0;
}
cVar2 = *(char *)(iVar5 + 9);
if (cVar2 == '\x11') {
*(uint *)(param_1 + 0x7e4) = (uint)*(ushort *)(iVar5 + 2);
func_0x01fb4b54(param_1,0x14);
func_0x01fb3ddc(param_1);
}
else {
if (cVar2 != '\x01') {
if (cVar2 == '\x06') {
piVar3 = (int *)func_0x01fc556c(0,*(undefined2 *)(param_1 + 0x7e6),3);
uVar4 = 0xffffffff;
if (piVar3 != (int *)0x0) {
iVar5 = 0;
piVar6 = piVar3;
do {
func_0x01fb99d4(piVar6[1],*(int *)(param_1 + 0x7d4) + iVar5,
*(undefined2 *)((int)piVar6 + 10));
puVar1 = (ushort *)((int)piVar6 + 10);
piVar6 = (int *)*piVar6;
iVar5 = iVar5 + (uint)*puVar1;
} while (piVar6 != (int *)0x0);
func_0x01fc7d20(piVar3);
halt_baddata();
}
}
else {
uVar4 = 0;
}
return uVar4;
}
*(uint *)(param_1 + 0x7e4) = (uint)*(ushort *)(iVar5 + 2);
func_0x01fb4b54(param_1,0x14);
func_0x01fb3e50(param_1);
}
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
3. Checksum (Sağlama Toplamı) Kontrolleri (FUN_000060b4 ve FUN_00003940)
Dosya bütünlüğünü doğrulamak için kodda iki farklı algoritma görünüyor:- CRC32:
FUN_000060b4fonksiyonu, bir CRC32 tablosu (0x7e0307f4sabiti ile ilişkili) kullanarak dosyanın sağlamasını yapıyor. - Basit Checksum:
FUN_00003940fonksiyonu, verileri 16-bitlik parçalar halinde toplayıp tersini alan (IP checksum benzeri) daha basit bir yöntem kullanıyor. - Güvenlik Açığı Potansiyeli: Eğer bootloader sadece basit checksum'ı kontrol ediyorsa, dosya üzerinde oynama yapmak kolaydır. Ancak CRC32 kontrolü varsa, değiştirdiğiniz dosyanın (header ekleseniz bile) CRC değerini yeniden hesaplayıp header'daki ilgili yere yazmanız gerekir.
C:
/* WARNING: Control flow encountered bad instruction data */
uint FUN_000060b4(uint param_1,uint param_2,int param_3)
{
byte bVar1;
byte *pbVar2;
byte *pbVar3;
uint uVar4;
uint uVar5;
undefined4 local_1030;
byte local_102c [4100];
local_1030 = 0;
if (param_3 != 0) {
if (param_2 != 0) {
do {
param_2 = param_2 - 1;
} while (param_2 != 0);
}
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
if (param_2 == 0) {
uVar4 = 0xffffffff;
}
else {
uVar5 = param_2 & 0xfff;
uVar4 = 0xffffffff;
pbVar2 = local_102c;
func_0x01fb9e20(param_1 & 0x3ffffff,uVar5,&local_1030,pbVar2);
if (uVar5 != 0) {
pbVar3 = pbVar2 + uVar5;
do {
bVar1 = *pbVar2;
pbVar2 = pbVar2 + 1;
uVar4 = *(uint *)(((uVar4 ^ bVar1) & 0xff) * 4 + -0x7e0307f4) ^ uVar4 >> 8;
} while (pbVar2 != pbVar3);
}
if (param_2 != uVar5) {
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
}
return uVar4;
}
C:
uint FUN_00003940(ushort *param_1,int param_2)
{
ushort uVar1;
uint uVar2;
int iVar3;
ushort *puVar4;
uint uVar5;
uVar5 = 0;
if (1 < param_2) {
uVar5 = 0;
puVar4 = param_1;
do {
uVar1 = *puVar4;
puVar4 = puVar4 + 1;
uVar5 = uVar5 + uVar1;
} while (puVar4 != param_1 + (param_2 - 2U >> 1) + 1);
uVar2 = param_2 - 2U >> 1;
param_2 = param_2 + -2 + uVar2 * -2;
param_1 = param_1 + uVar2 + 1;
}
if (param_2 == 1) {
uVar5 = uVar5 + (uint)*(byte *)param_1 * 0x100;
}
iVar3 = (uVar5 & 0xffff) + ((int)uVar5 >> 0x10);
return ~((iVar3 >> 0x10) + iVar3) & 0xffff;
}
4. Gizli Fonksiyonlar ve Switch-Case Yapısı (FUN_000041a4)
Dosya adı kontrolünden (FUN_00004538) gelen sonuca göre FUN_000041a4 fonksiyonu farklı işlemleri tetikler:
- Case 1-4: Standart firmware ve config yükleme rutinleri.
- Case 5 & 6: Bu kısımlar ilginçtir. Kodda
_DAT_81fd6480 + -0x10000gibi bellek kaydırma işlemleri yapılıyor. Bu, bootloader'ın kendisine (veya kritik bir flash bölgesine) yazma yetkisi veren gizli bir mod olabilir. Bu moda ulaşmak için doğru dosya ismini (örneğintcboot.binveyatclinux_chk.bingibi) bulmanız gerekir.
C:
/* WARNING: Control flow encountered bad instruction data */
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
undefined4 FUN_000041a4(int param_1)
{
ushort uVar1;
int iVar2;
undefined4 uVar3;
uint uVar4;
int iVar5;
int iVar6;
undefined1 auStack_18 [8];
iVar2 = func_0x01fb39f4();
uVar3 = 0xffffffff;
if (iVar2 == _DAT_81fd5a88) {
uVar4 = func_0x01fb3d08(param_1);
uVar3 = 0xffffffff;
if (_DAT_81fd5a8c == uVar4) {
iVar2 = *(int *)(param_1 + 0x7d4);
uVar1 = *(ushort *)(iVar2 + 2);
if (uVar1 == _DAT_81fd5a84) {
iVar6 = *(int *)(param_1 + 0x7e4) + -4;
iVar5 = func_0x01fb49f4(iVar2 + 4,iVar6);
uVar3 = 0xffffffff;
if (iVar5 == 0) {
_DAT_81fd6480 = iVar6 + _DAT_81fd6480;
func_0x01fb4120(iVar2,_DAT_81fd5a84);
_DAT_81fd5a84 = _DAT_81fd5a84 + 1;
uVar3 = 0;
if (iVar6 < 0x200) {
func_0x01fb4990();
iVar2 = func_0x01fb3f40((int)_DAT_81fd6484,_DAT_81fd6480,0x80020000);
uVar3 = 0;
if (iVar2 == 0) {
iVar2 = func_0x01fb5fb0();
if (iVar2 != 0) {
_DAT_81fd4440 = 0x23e0000;
_DAT_81fd4444 = 0x25e0000;
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
_DAT_81fd4440 = 0x1e0000;
_DAT_81fd4444 = 0x3e0000;
if (_DAT_81fd6484 == 1) {
func_0x01fb8cbc(0x81fd1818,_DAT_81fd6480);
func_0x01fb9f00(0,_DAT_81fd6480);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(0,_DAT_81fd6480,auStack_18,0x80020000);
halt_baddata();
}
if (_DAT_81fd6484 == 2) {
func_0x01fb8cbc(0x81fd1850,_DAT_81fd6480);
func_0x01fb9f00(_DAT_81fd5aac,_DAT_81fd6480);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(_DAT_81fd5aac,_DAT_81fd6480,auStack_18,0x80020000);
halt_baddata();
}
if (_DAT_81fd6484 == 3) {
func_0x01fb8cbc(0x81fd188c,0x1e0000,_DAT_81fd6480);
func_0x01fb9f00(_DAT_81fd4440,_DAT_81fd6480);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(_DAT_81fd4440,_DAT_81fd6480,auStack_18,0x80020000);
halt_baddata();
}
if (_DAT_81fd6484 == 4) {
func_0x01fb8cbc(0x81fd188c,0x3e0000,_DAT_81fd6480);
func_0x01fb9f00(_DAT_81fd4444,_DAT_81fd6480);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(_DAT_81fd4444,_DAT_81fd6480,auStack_18,0x80020000);
halt_baddata();
}
if (_DAT_81fd6484 == 5) {
func_0x01fb8cbc(0x81fd18c4,_DAT_81fd6480 + -0x10000);
func_0x01fb8cbc(0x81fd1900,0x8000000,_DAT_81fd6a60);
func_0x01fb9f00(_DAT_81fd6a60,0x8000000);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(_DAT_81fd6a60,_DAT_81fd6480 + -0x10000,auStack_18,0x80020000);
halt_baddata();
}
if (_DAT_81fd6484 == 6) {
func_0x01fb8cbc(0x81fd1924,_DAT_81fd6480);
func_0x01fb9f00(_DAT_81fd4460,_DAT_81fd6480);
func_0x01fb8cbc(0x81fd4070);
func_0x01fb9d40(_DAT_81fd4460,_DAT_81fd6480,auStack_18,0x80020000);
halt_baddata();
}
func_0x01fb8cbc(0x81fd1960);
halt_baddata();
}
}
}
}
else {
if (uVar1 < _DAT_81fd5a84) {
func_0x01fb4120(iVar2,uVar1);
/* WARNING: Bad instruction - Truncating control flow here */
halt_baddata();
}
func_0x01fb4120(iVar2);
uVar3 = 0;
}
}
}
return uVar3;
}
Özet ve Eylem Planı
Bootloader'daki httpd (web sunucusu) korumasını aşmak için şu adımları izleyebilirsiniz:- İsim Değişikliği: Dosyanızın adını kesinlikle tclinux.bin yapın.
FUN_00004538'deki "whitelist" (izinli liste) kontrolünü geçmenin en kolay yolu budur. - Header Ekleme: mtd6_backup.bin ham bir döküm (raw dump) ise, bootloader bunu kabul etmez. Çalışan bir firmware dosyasının ilk 64 veya 256 baytlık kısmını (header) kendi dosyanızın başına kopyalayın.
- Magic Byte Kontrolü: Dosyanızın başında 54 32 12 53 (veya endian'a göre tersi) olduğundan emin olun.
Son düzenleme: