Реверс алгоритма из прошивки устройства на базе ARM-процессора

от автора

Постановка задачи

Есть устройство, работает с чипами ss02-1, умеет в них писать и читать. Для этого в себе содержит алгоритмы генерации паролей на авторизацию и запись, мы хотим разобрать алгоритм и написать код, который будет выдавать тот же результат.

Что имеем — прошивку устройства, серийный номер чипа, на основание которого генерируются пароли. Устройство xerox wc 4250, прошивка у меня в наличии версии 15.003.70.000.

Выбор инструментов

  • На первом месте Ida. Интерактивный дизассемблер, инструмент для анализа кода, загрузим прошивку, восстановим порядок генерации, определим какие функции что делают, построим первоначальный каркас будущей программы.

  • TRACE32 Arm Debugger от lauterbach. Откровенно говоря, у меня старая версия, в about написано Release Jun 2011. Возможно сейчас есть и другие инструменты, но и этот отлично справляется с задачей. В нем можно создать виртуальную среду, выбрать тип эмулируемого процессора, загрузить прошивку, запустить на выполнение и получить результат. Можно выполнять пошагово сверяясь со своим кодом, искать ошибки.

  • Python — тут пишем код.

Первый взгляд

Для начала нужно достать из прошивки ядро, оно после сигнатуры “$ZIP”, начиная с 0x78 0x9C — zip архив. Пишем код:

import zlibdef read_u32(tab, addr):    res = tab[addr]    res = res << 8 | tab[addr+1]    res = res << 8 | tab[addr+2]    res = res << 8 | tab[addr+3]    return reswith open("WC4250_15.003.70.000.hd", 'rb') as f:    data = f.read()pos = 0while True:    pos = data.find(b"$ZIP", pos)    if pos == -1:        break    filename_bytes = data[pos + 4:pos + 8]    filename_hex = filename_bytes.hex().upper()    block_size = read_u32(data,8)     block_start = pos + 12    compressed_data = data[block_start:block_start + block_size]    if compressed_data[:2] == b'\x78\x9C':        filename = f"{filename_hex}.bin"        decompressed_data = zlib.decompress(compressed_data)        with open(filename, 'wb') as f:            f.write(decompressed_data)        pos += 12 + block_size    else:        pos += 1

Грузим в ida, ищем нужную процедурку. Пропускаю подробности, т.к. задачка в алгоритме, на нем подробнее.

Под спойлером функция sub_203D548. Судя по строковым константам INSTALL_TONER, CHIPv1.0…Invalid, INVALID_TONER то что нужно.

Листинг функции sub_203D548 как есть
ROM:0203D548 sub_203D548                             ; CODE XREF: sub_1D848C4+34pROM:0203D548                                         ; sub_1D84CA8+4pROM:0203D548ROM:0203D548 var_64          = -0x64ROM:0203D548 var_5C          = -0x5CROM:0203D548 var_54          = -0x54ROM:0203D548 var_48          = -0x48ROM:0203D548 var_40          = -0x40ROM:0203D548 var_30          = -0x30ROM:0203D548 var_1C          = -0x1CROM:0203D548 var_16          = -0x16ROM:0203D548 var_15          = -0x15ROM:0203D548 var_14          = -0x14ROM:0203D548 var_E           = -0xEROM:0203D548 var_D           = -0xDROM:0203D548ROM:0203D548                 STMFD   SP!, {R4,R5,LR}ROM:0203D54C                 SUB     SP, SP, #0x60ROM:0203D550                 ADD     R0, SP, #0x50ROM:0203D554                 MOV     R1, #0ROM:0203D558                 MOV     R2, #0ROM:0203D55C                 MOV     R3, #0ROM:0203D560                 MOV     R4, #0ROM:0203D564                 STMIA   R0, {R1-R4} ROM:0203D568                 ADD     R0, SP, #0x2CROM:0203D56C                 MOV     R1, #0ROM:0203D570                 MOV     R2, #0ROM:0203D574                 MOV     R4, #0ROM:0203D578                 MOV     R3, #0ROM:0203D57C                 STMIA   R0, {R1-R4}ROM:0203D580                 ADD     R0, SP, #0x24ROM:0203D584                 MOV     R1, #0ROM:0203D588                 MOV     R2, #0ROM:0203D58C                 STMIA   R0, {R1,R2}ROM:0203D590                 LDR     R4, =0x28A7708ROM:0203D594                 LDRB    R0, [R4]ROM:0203D598                 MOV     R1, R0,LSL#4ROM:0203D59C                 LDR     R0, =dword_224A6B0ROM:0203D5A0                 STRB    R1, [R0]ROM:0203D5A4                 BL      sub_203D4A4ROM:0203D5A8                 CMP     R0, #1ROM:0203D5AC                 BNE     loc_203D5C8ROM:0203D5B0                 LDRB    R1, [R4]ROM:0203D5B4                 ADR     R0, aInstall_tonerD ; "\r\n INSTALL_TONER [%d] "ROM:0203D5B8                 BL      sub_1FF2738ROM:0203D5BC                 MOV     R0, #1ROM:0203D5C0                 ADD     SP, SP, #0x60ROM:0203D5C4                 LDMFD   SP!, {R4,R5,PC}ROM:0203D5C8 ; ---------------------------------------------------------------------------ROM:0203D5C8ROM:0203D5C8 loc_203D5C8                             ; CODE XREF: sub_203D548+64jROM:0203D5C8                 ADD     R1, SP, #0x50ROM:0203D5CC                 MOV     R2, #8ROM:0203D5D0                 MOV     R0, #0x10ROM:0203D5D4                 BL      sub_1D849ECROM:0203D5D8                 LDRB    R0, [SP,#0x56]ROM:0203D5DC                 CMP     R0, #0x90ROM:0203D5E0                 LDREQB  R0, [SP,#0x57]ROM:0203D5E4                 CMPEQ   R0, #0x1BROM:0203D5E8                 BEQ     loc_203D5F8ROM:0203D5EC                 LDRB    R1, [R4]ROM:0203D5F0                 ADR     R0, aSchipv1_0__inv ; "\r\n sCHIPv1.0..Invalid [%d] "ROM:0203D5F4                 BL      sub_1FF2738ROM:0203D5F8ROM:0203D5F8 loc_203D5F8                             ; CODE XREF: sub_203D548+A0jROM:0203D5F8                 ADD     R0, SP, #0x58ROM:0203D5FC                 ADR     R1, aSecprt     ROM:0203D600                 MOV     R2, #6ROM:0203D604                 BL      memcpy          ROM:0203D608                 MOV     R0, #0ROM:0203D60CROM:0203D60C loc_203D60C                             ; CODE XREF: sub_203D548+F8jROM:0203D60C                 ADD     R1, SP, #0x50ROM:0203D610                 LDRB    R1, [R1,R0]ROM:0203D614                 LDRB    R2, [SP,#0x5E]ROM:0203D618                 EOR     R1, R2, R1ROM:0203D61C                 STRB    R1, [SP,#0x5E]ROM:0203D620                 ADD     R1, SP, #0x50ROM:0203D624                 LDRB    R1, [R1,R0,LSL#1]ROM:0203D628                 LDRB    R2, [SP,#0x5F]ROM:0203D62C                 ADD     R0, R0, #1ROM:0203D630                 AND     R0, R0, #0xFFROM:0203D634                 EOR     R1, R2, R1ROM:0203D638                 STRB    R1, [SP,#0x5F]ROM:0203D63C                 CMP     R0, #8ROM:0203D640                 BLT     loc_203D60C     ROM:0203D644                 ADD     R1, SP, #0x3C   ROM:0203D648                 ADD     R0, SP, #0x50   ROM:0203D64C                 MOV     R2, #0x10ROM:0203D650                 BL      sub_1DBE83C                                   ROM:0203D654                 ADD     R2, SP, #0x10ROM:0203D658                 ADD     R0, SP, #0x3CROM:0203D65C                 MOV     R1, #0x10ROM:0203D660                 BL      SHA_1           ROM:0203D660                                         ROM:0203D664                 ADD     R1, SP, #0x18ROM:0203D668                 ADD     R0, SP, #0x24ROM:0203D66C                 MOV     R2, #8ROM:0203D670                 BL      memcpy         ROM:0203D674                 MOV     R1, SPROM:0203D678                 ADD     R0, SP, #0x10   ROM:0203D67C                 MOV     R2, #0x10ROM:0203D680                 BL      sub_1DBE83C     ROM:0203D680                                         ROM:0203D684                 ADD     R1, SP, #8ROM:0203D688                 ADD     R0, SP, #0x2CROM:0203D68C                 MOV     R2, #8ROM:0203D690                 BL      memcpyROM:0203D694                 ADD     R1, SP, #0x2CROM:0203D698                 LDMIA   R1, {R2,R3,R12,LR}ROM:0203D69C                 ADD     R0, SP, #0x3CROM:0203D6A0                 STMIA   R0, {R2,R3,R12,LR}ROM:0203D6A4                 MOV     R3, #1ROM:0203D6A8                 MOV     R2, R5ROM:0203D6AC                 MOV     R0, #1ROM:0203D6B0                 ADD     R1, SP, #0x3CROM:0203D6B4                 BL      sub_203D360ROM:0203D6B8                 MOV     R5, #2ROM:0203D6BC                 CMP     R0, #0ROM:0203D6C0                 BEQ     loc_203D6E4ROM:0203D6C4                 ADR     R0, aCrumCoreFileFa ; "\r\n[Crum Core file] Fail cm_ActiveSecuri"...ROM:0203D6C8                 BL      sub_1FF2738ROM:0203D6CC                 LDRB    R1, [R4]ROM:0203D6D0                 ADR     R0, aInvalid_tonerD ; "\r\n INVALID_TONER [%d] "ROM:0203D6D4                 BL      sub_1FF2738ROM:0203D6D8                 MOV     R0, R5ROM:0203D6DC                 ADD     SP, SP, #0x60ROM:0203D6E0                 LDMFD   SP!, {R4,R5,PC}ROM:0203D6E4 ; ---------------------------------------------------------------------------ROM:0203D6E4ROM:0203D6E4 loc_203D6E4                             ; CODE XREF: sub_203D548+178jROM:0203D6E4                 ADD     R0, SP, #0x6C+var_48ROM:0203D6E8                 MOV     R2, #0ROM:0203D6EC                 MOV     R1, #1ROM:0203D6F0                 BL      sub_203D148ROM:0203D6F4                 CMP     R0, #0ROM:0203D6F8                 BEQ     loc_203D71CROM:0203D6FC                 ADR     R0, aCrumCoreFile_0 ; "\r\n[Crum Core file] Fail cm_VerifyPasswo"...ROM:0203D700                 BL      sub_1FF2738ROM:0203D704                 LDRB    R1, [R4]ROM:0203D708                 ADR     R0, aInvalid_tonerD ; "\r\n INVALID_TONER [%d] "ROM:0203D70C                 BL      sub_1FF2738ROM:0203D710                 MOV     R0, R5ROM:0203D714                 ADD     SP, SP, #0x60ROM:0203D718                 LDMFD   SP!, {R4,R5,PC}ROM:0203D71C ; ---------------------------------------------------------------------------ROM:0203D71CROM:0203D71C loc_203D71C                             ; CODE XREF: sub_203D548+1B0jROM:0203D71C                 MOV     R1, #1ROM:0203D720                 BL      nullsub_154ROM:0203D724                 MOV     R0, #0ROM:0203D728                 ADD     SP, SP, #0x60ROM:0203D72C                 LDMFD   SP!, {R4,R5,PC}ROM:0203D72C ; End of function sub_203D548ROM:0203D72CROM:0203D72C ; ---------------------------------------------------------------------------ROM:0203D730 off_203D730     DCD dword_224A6B0       ; DATA XREF: sub_203D548+54rROM:0203D730                                         ; sub_203D7E0+9Cr ...ROM:0203D734 aInstall_tonerD DCB 0xD,0xA             ; DATA XREF: sub_203D548+6CoROM:0203D734                 DCB " INSTALL_TONER [%d] ",0ROM:0203D74B                 DCB 0ROM:0203D74C aSchipv1_0__inv DCB 0xD,0xA             ; DATA XREF: sub_203D548+A8oROM:0203D74C                                         ; ROM:0203D8BCo ...ROM:0203D74C                 DCB " sCHIPv1.0..Invalid [%d] ",0ROM:0203D768 aSecprt         DCB "SECPRT",0          ; DATA XREF: sub_203D548+B4oROM:0203D768                                         ; ROM:0203D8C8oROM:0203D76F                 DCB 0ROM:0203D770 aCrumCoreFileFa DCB 0xD,0xA             ; DATA XREF: sub_203D548+17CoROM:0203D770                 DCB "[Crum Core file] Fail cm_ActiveSecurity",0ROM:0203D79A                 DCW 0ROM:0203D79C aInvalid_tonerD DCB 0xD,0xA             ; DATA XREF: sub_203D548+188oROM:0203D79C                                         ; sub_203D548+1C0oROM:0203D79C                 DCB " INVALID_TONER [%d] ",0ROM:0203D7B3                 DCB 0ROM:0203D7B4 aCrumCoreFile_0 DCB 0xD,0xA             ; DATA XREF: sub_203D548+1B4oROM:0203D7B4                 DCB "[Crum Core file] Fail cm_VerifyPassword",0ROM:0203D7DE                 DCW 0ROM:0203D7E0

Краткий алгоритм работы такой:

  • Выделяем место в стеке, чистим.

  • Читаем серийный номер, кладем по адресу 0x50

  • Кладем по адресу 0x50 строку “SECPRT”

  • 0203D60C – 0203D640 что то считается из sn и кладется в 5e-5f

  • sub_1DBE83C ; Что-то считает (куда=3c, откуда=50, всего = x0x10)

  • sub_1BA543C ; Что-то считает (куда=10, откуда=3c, всего = x0x10)

  • sub_1DBE83C ; Что-то считает (куда=0x0, откуда=0x10, всего = x0x10)

Под спойлером прокомментировал листинг как я это понимаю.

Листинг функции sub_203D548 с разбором
ROM:0203D548 ; =============== S U B R O U T I N E =======================================ROM:0203D548ROM:0203D548ROM:0203D548 sub_203D548                             ; CODE XREF: sub_1D848C4+34pROM:0203D548                                         ; sub_1D84CA8+4pROM:0203D548ROM:0203D548 var_64          = -0x64ROM:0203D548 var_5C          = -0x5CROM:0203D548 var_54          = -0x54ROM:0203D548 var_48          = -0x48ROM:0203D548 var_40          = -0x40ROM:0203D548 var_30          = -0x30ROM:0203D548 var_1C          = -0x1CROM:0203D548 var_16          = -0x16ROM:0203D548 var_15          = -0x15ROM:0203D548 var_14          = -0x14ROM:0203D548 var_E           = -0xEROM:0203D548 var_D           = -0xDROM:0203D548ROM:0203D548                 STMFD   SP!, {R4,R5,LR}ROM:0203D54C                 SUB     SP, SP, #0x60   ; Выделяем блок размером 0x60ROM:0203D550                 ADD     R0, SP, #0x50ROM:0203D554                 MOV     R1, #0ROM:0203D558                 MOV     R2, #0ROM:0203D55C                 MOV     R3, #0ROM:0203D560                 MOV     R4, #0ROM:0203D564                 STMIA   R0, {R1-R4}     ; обнуляем область [0x50-0x60]ROM:0203D564                                         ;ROM:0203D568                 ADD     R0, SP, #0x2CROM:0203D56C                 MOV     R1, #0ROM:0203D570                 MOV     R2, #0ROM:0203D574                 MOV     R4, #0ROM:0203D578                 MOV     R3, #0ROM:0203D57C                 STMIA   R0, {R1-R4}     ; обнуляем область [0x2с-0x3с]ROM:0203D57C                                         ;ROM:0203D580                 ADD     R0, SP, #0x24ROM:0203D584                 MOV     R1, #0ROM:0203D588                 MOV     R2, #0ROM:0203D58C                 STMIA   R0, {R1,R2}     ; обнуляем область [0x24-(0x24+8)]ROM:0203D58C                                         ;ROM:0203D590                 LDR     R4, =0x28A7708ROM:0203D594                 LDRB    R0, [R4]ROM:0203D598                 MOV     R1, R0,LSL#4ROM:0203D59C                 LDR     R0, =dword_224A6B0ROM:0203D5A0                 STRB    R1, [R0]ROM:0203D5A4                 BL      sub_203D4A4     ; Кажется проверяет наличие чипа в принципеROM:0203D5A8                 CMP     R0, #1ROM:0203D5AC                 BNE     loc_203D5C8ROM:0203D5B0                 LDRB    R1, [R4]ROM:0203D5B4                 ADR     R0, aInstall_tonerD ; "\r\n INSTALL_TONER [%d] "ROM:0203D5B8                 BL      printROM:0203D5BC                 MOV     R0, #1ROM:0203D5C0                 ADD     SP, SP, #0x60ROM:0203D5C4                 LDMFD   SP!, {R4,R5,PC}ROM:0203D5C8 ; ---------------------------------------------------------------------------ROM:0203D5C8ROM:0203D5C8 loc_203D5C8                             ; CODE XREF: sub_203D548+64jROM:0203D5C8                 ADD     R1, SP, #0x50   ; Мы тут если все хорошоROM:0203D5CC                 MOV     R2, #8ROM:0203D5D0                 MOV     R0, #0x10ROM:0203D5D4                 BL      sub_1D849EC     ; Думаю тут чтение серийного номера, кладется по адресу 0x50ROM:0203D5D4                                         ; т.к. далее проверяется его хвостROM:0203D5D4                                         ;ROM:0203D5D8                 LDRB    R0, [SP,#0x56]ROM:0203D5DC                 CMP     R0, #0x90ROM:0203D5E0                 LDREQB  R0, [SP,#0x57]ROM:0203D5E4                 CMPEQ   R0, #0x1BROM:0203D5E8                 BEQ     loc_203D5F8     ; если 2 последних символа 90 1B  - чип нормальныйROM:0203D5EC                 LDRB    R1, [R4]ROM:0203D5F0                 ADR     R0, aSchipv1_0__inv ; "\r\n sCHIPv1.0..Invalid [%d] "ROM:0203D5F4                 BL      printROM:0203D5F8ROM:0203D5F8 loc_203D5F8                             ; CODE XREF: sub_203D548+A0jROM:0203D5F8                 ADD     R0, SP, #0x58   ; ! Отсюда начинаются манипуляции с серийным номеромROM:0203D5FC                 ADR     R1, aSecprt     ; "SECPRT"ROM:0203D600                 MOV     R2, #6ROM:0203D604                 BL      memcpy          ; копируем SECPRT по адресу 0x58ROM:0203D608                 MOV     R0, #0ROM:0203D60CROM:0203D60C loc_203D60C                             ; CODE XREF: sub_203D548+F8jROM:0203D60C                 ADD     R1, SP, #0x50ROM:0203D610                 LDRB    R1, [R1,R0]ROM:0203D614                 LDRB    R2, [SP,#0x5E]ROM:0203D618                 EOR     R1, R2, R1ROM:0203D61C                 STRB    R1, [SP,#0x5E]ROM:0203D620                 ADD     R1, SP, #0x50ROM:0203D624                 LDRB    R1, [R1,R0,LSL#1]ROM:0203D628                 LDRB    R2, [SP,#0x5F]ROM:0203D62C                 ADD     R0, R0, #1ROM:0203D630                 AND     R0, R0, #0xFFROM:0203D634                 EOR     R1, R2, R1ROM:0203D638                 STRB    R1, [SP,#0x5F]ROM:0203D63C                 CMP     R0, #8ROM:0203D640                 BLT     loc_203D60C     ; hash SN по адресу 0x5e - 0x5fROM:0203D644                 ADD     R1, SP, #0x3C   ; r1 = 3cROM:0203D648                 ADD     R0, SP, #0x50   ; r0 = 50ROM:0203D64C                 MOV     R2, #0x10ROM:0203D650                 BL      sub_1DBE83C     ; Что-то считает (куда=3c, откуда=50, всего = x0x10)ROM:0203D650                                         ;ROM:0203D654                 ADD     R2, SP, #0x10ROM:0203D658                 ADD     R0, SP, #0x3CROM:0203D65C                 MOV     R1, #0x10ROM:0203D660                 BL      sub_1BA543C     ; Что-то считает (куда=10, откуда=3c, всего = x0x10)ROM:0203D664                 ADD     R1, SP, #0x18ROM:0203D668                 ADD     R0, SP, #0x24ROM:0203D66C                 MOV     R2, #8ROM:0203D670                 BL      memcpyROM:0203D674                 MOV     R1, SPROM:0203D678                 ADD     R0, SP, #0x10ROM:0203D67C                 MOV     R2, #0x10ROM:0203D680                 BL      sub_1DBE83C     ; опять что-то считает (куда=0x0, откуда=0x10, всего = x0x10)ROM:0203D684                 ADD     R1, SP, #8ROM:0203D688                 ADD     R0, SP, #0x2CROM:0203D68C                 MOV     R2, #8ROM:0203D690                 BL      memcpyROM:0203D694                 ADD     R1, SP, #0x2CROM:0203D698                 LDMIA   R1, {R2,R3,R12,LR}ROM:0203D69C                 ADD     R0, SP, #0x3CROM:0203D6A0                 STMIA   R0, {R2,R3,R12,LR}ROM:0203D6A4                 MOV     R3, #1ROM:0203D6A8                 MOV     R2, R5ROM:0203D6AC                 MOV     R0, #1ROM:0203D6B0                 ADD     R1, SP, #0x3C   ; значит в 3c auth-passROM:0203D6B0                                         ; до этого копировали c 0x8 в 0x2с, c 0x2c в 0x3cROM:0203D6B4                 BL      sub_203D360     ; Вероятно авторизацияROM:0203D6B8                 MOV     R5, #2ROM:0203D6BC                 CMP     R0, #0ROM:0203D6C0                 BEQ     loc_203D6E4ROM:0203D6C4                 ADR     R0, aCrumCoreFileFa ; "\r\n[Crum Core file] Fail cm_ActiveSecuri"...ROM:0203D6C8                 BL      printROM:0203D6CC                 LDRB    R1, [R4]ROM:0203D6D0                 ADR     R0, aInvalid_tonerD ; "\r\n INVALID_TONER [%d] "ROM:0203D6D4                 BL      printROM:0203D6D8                 MOV     R0, R5ROM:0203D6DC                 ADD     SP, SP, #0x60ROM:0203D6E0                 LDMFD   SP!, {R4,R5,PC}ROM:0203D6E4 ; ---------------------------------------------------------------------------ROM:0203D6E4ROM:0203D6E4 loc_203D6E4                             ; CODE XREF: sub_203D548+178jROM:0203D6E4                 ADD     R0, SP, #0x24   ; значит в 0x24 write-passROM:0203D6E8                 MOV     R2, #0ROM:0203D6EC                 MOV     R1, #1ROM:0203D6F0                 BL      sub_203D148     ; Вероятно запись после успешной авторизацииROM:0203D6F0                                         ;ROM:0203D6F4                 CMP     R0, #0ROM:0203D6F8                 BEQ     loc_203D71CROM:0203D6FC                 ADR     R0, aCrumCoreFile_0 ; "\r\n[Crum Core file] Fail cm_VerifyPasswo"...ROM:0203D700                 BL      printROM:0203D704                 LDRB    R1, [R4]ROM:0203D708                 ADR     R0, aInvalid_tonerD ; "\r\n INVALID_TONER [%d] "ROM:0203D70C                 BL      printROM:0203D710                 MOV     R0, R5ROM:0203D714                 ADD     SP, SP, #0x60ROM:0203D718                 LDMFD   SP!, {R4,R5,PC}ROM:0203D71C ; ---------------------------------------------------------------------------ROM:0203D71CROM:0203D71C loc_203D71C                             ; CODE XREF: sub_203D548+1B0jROM:0203D71C                 MOV     R1, #1ROM:0203D720                 BL      nullsub_154ROM:0203D724                 MOV     R0, #0ROM:0203D728                 ADD     SP, SP, #0x60ROM:0203D72C                 LDMFD   SP!, {R4,R5,PC}ROM:0203D72C ; End of function sub_203D548

Выходит, что по сути нужны 2 функции 1DBE83C и 1BA543C. Посмотрим в эмуляторе какой результат они возвращают, если повезет — попробуем подобрать что-то стандартное, если нет — будем их разбирать.

Пишем первую версию:

mem = bytearray(0x60)#serial = input("SN:")serial = "112233445566901B"auth, write = generate_passwords(serial)dump(mem, 0, 0x60)def dump(tab,start, ln):    for offset in range(start, start + ln, 16):        chunk = tab[offset:offset + 16]        print(f"{hex(offset)}: {' '.join(f'{b:02X}' for b in chunk)}" )def generate_passwords(serial_hex):    global mem    sn_bytes = bytes.fromhex(serial_hex)    if not((sn_bytes[6]==0x90) & (sn_bytes[7]==0x1B)):        print ("not ss02-1 crum")        return bytes.fromhex("00"), bytes.fromhex("00")    mem[0x50:0x58] = sn_bytes    mem[0x58:0x5E] = b"SECPRT"    mem[0x5E] = 0    mem[0x5F] = 0    for r0 in range(8):        mem[0x5E] = mem[0x5E] ^ mem[0x50 + r0]        mem[0x5F] = mem[0x5F] ^ mem[0x50 + (r0 << 1)]    sub_1DBE83C (r0 = 0x50, r1 = 0x3c, r2 = 0x10)    sub_1BA543C (r0 = 0x3c, r1, 0x10, r2 = 0x10)    mem [0x24:0x2c] = mem[0x18:0x20]    sub_1DBE83C (r0 = 0x10, r1 = 0x0, r2 = 0x10)    mem[0x2c:0x2c+8] = mem[0x8:0x10]    auth_pass = mem[0x2c:0x2C+8]    write_pass = mem[0x24:0x27]    return auth_pass, write_passdef sub_1DBE83C (r0, r1, r2):    returndef sub_1BA543C (r0, r1, r2)    return

Результат:

0x0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x50: 11 22 33 44 55 66 90 1B 53 45 43 50 52 54 FC 59

Эмуляция, получение результата

Запускаем эмулятор. Первым делом надо выбрать тип процессора, установить режим bigendian, включить. CPU \ System Settings…

Настраиваем окошки: листинг (View / List Source), регистры (View / Registers), дамп по адресу 0x0 (View / Dump…)- там будем собирать результат. Кликая в дампе по адресам 0x50 – 0x58 вводим свой серийник.

Все команды по сути выполняются в командной строке внизу окна. Если мы кликаем на адрес памяти для модификации система автоматически пишет команду для изменения значения по этому адресу, нам остается толко ввести значение. Например при заполнении серийника создалась команда «SD:0x50 %LE «. При модификации регистра PC — «R.S PC «, сокращенно от «REGISTER.SET PC «, такая команда тоже работает. Под командной строкой есть кнопки, отображающие какие команды доступны на текущем этапе. Можно натыкивать команды кнопками, пока не запомнте те что нужны. Дальше нужно загрузить прошивку, установить значения регистров. Для загрузки дампа натыкиваем кнопками:

DATA.LOAD.BINARY "kernel.bin" 0x1B60000R.S PC 0x203D5D8

Мы в начале пути, 0x203D5D8 выбран потому что это начало проверки хвоста серийника. F2 — пошаговое выполнение команды, F3 — не заходя в процедуры. Прошагиваем весь код по F3 до 0203D644, перед началом вызова функций.

Результат:

Смотрим хвост, FC 59, сошлось, ура ! ) Можно прошагать до конца, посмотреть как заполняется область памяти. На этом этапе я бы хотел сделать небольшое отступление. В процессе отладки придется не раз начинать с начала, каждый раз всё настраивать, дошагивать до нужной точки нереально. В эмуляторе есть инструмент для облегчения задачи — batchfile — командный файл, где мы пишем все команды загрузки, инициализации. Запуск через File / Run batchfile… Доступны все команды, даже отладка, т.е. можно сделать шаги по f2 (команда STEP), запустить на выполнение (GO) установить break — (BREAK.SET). Напишем такой файл:

b::resetsystem.option.bigendian onsystem.updata.load.binary "kernel.bin" 0x1B60000data.set 0x50 %BYTE 0x11data.set 0x51 %BYTE 0x22data.set 0x52 %BYTE 0x33data.set 0x53 %BYTE 0x44data.set 0x54 %BYTE 0x55data.set 0x55 %BYTE 0x66data.set 0x56 %BYTE 0x90data.set 0x57 %BYTE 0x1Bregister.set.pc 0x203D5D8b.s 0x0203D644go

Всё, теперь мы опять в той же точке без настроек. Еще дополнение: система не ждет прохождение до точки останова. Если сразу после go сохранить результат, то он может оказаться не готов. Если задача остановиться после вызова процедуры и сохранить результат, нужно дать время на выполнение этой функции. В интерактивном режиме мы видим когда процессор занят, в batch файле нет, команды начнут выполняться дальше не дожидаясь. Чтобы решить это нужно вставить паузу, команда WAIT, например “wait 200.ms”. Какую паузу ставить решаете сами, предварительно оценив время выполнения функции руками.

Пробежимся по функциям, выпишем результат после каждой:

sub_1DBE83C(11 22 33 44 55 66 90 1B 53 45 43 50 52 54 FC 59) = 78 07 FE 92 F2 4F 15 61 D6 A7 9A CE 85 07 82 65sub_1BA543C(78 07 FE 92 F2 4F 15 61 D6 A7 9A CE 85 07 82 65) = E7 16 A6 FE 0E 4D 16 FC 26 85 1F 08 FD 9C FC 30 2E 2A 66 2Fsub_1DBE83C(E7 16 A6 FE 0E 4D 16 FC 26 85 1F 08 FD 9C FC 30) = 3F AC 9A 28 5C 8E 1D 2D 39 1B 22 CD 6D D7 B5 C4

Самым логичным ходом будет попробовать подобрать готовые алгоритмы, вдруг повезет. Пишем тест:

import hashlibdef test_alg(source, res_ok):    alg = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',           'blake2b', 'blake2s',           'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512')    for name in alg:        if hashlib.new(name, source).hexdigest() == res_ok.hex():            return name    return Falsetests =((bytes.fromhex("11 22 33 44 55 66 90 1B 53 45 43 50 52 54 FC 59"), bytes.fromhex("78 07 FE 92 F2 4F 15 61 D6 A7 9A CE 85 07 82 65")),(bytes.fromhex("78 07 FE 92 F2 4F 15 61 D6 A7 9A CE 85 07 82 65"), bytes.fromhex("E7 16 A6 FE 0E 4D 16 FC 26 85 1F 08 FD 9C FC 30 2E 2A 66 2F")),(bytes.fromhex("E7 16 A6 FE 0E 4D 16 FC 26 85 1F 08 FD 9C FC 30"), bytes.fromhex("3F AC 9A 28 5C 8E 1D 2D 39 1B 22 CD 6D D7 B5 C4")))for i, tst in enumerate(tests):    print (i,  test_alg (tst[0], tst[1]))

Результат:

0 False1 sha12 False

Бинго! sub_1BA543C — это SHA-1, можно использовать библиотечную функцию, откровенно говоря — повезло ) Едем дальше, открываем sub_1DBE83C. Выглядит не страшно, всего 2 вызова:

ROM:01DBE83C sub_1DBE83C                                                                   ROM:01DBE83C                 STMFD   SP!, {R4,R5,LR}ROM:01DBE840                 SUB     SP, SP, #0xA0; свой блок данных размером 0xA0ROM:01DBE844                 MOV     R4, R1ROM:01DBE848                 LDR     R1, =0x2105B04; тут лежат константыROM:01DBE84C                 MOV     R5, R0ROM:01DBE850                 LDMIA   R1, {R1,R3,R12,LR}ROM:01DBE854                 ADD     R0, SP, #0x10ROM:01DBE858                 STMIA   R0, {R1,R3,R12,LR}; запишем себеROM:01DBE85C                 LDR     R1, =0x2105B14; и тут константыROM:01DBE860                 MOV     R0, SPROM:01DBE864                 LDMIA   R1, {R1,R3,R12,LR}ROM:01DBE868                 STMIA   R0, {R1,R3,R12,LR}ROM:01DBE86C                 ADD     R1, SP, #0x20ROM:01DBE870                 ADD     R0, SP, #0x10ROM:01DBE874                 BL      sub_1DBC554ROM:01DBE878                 ADD     R2, SP, #0x20   ROM:01DBE87C                 MOV     R1, R4          ROM:01DBE880                 MOV     R0, R5          ROM:01DBE884                 BL      sub_1DBCEF0ROM:01DBE888                 ADD     SP, SP, #0xA0ROM:01DBE88C                 LDMFD   SP!, {R4,R5,PC}ROM:01DBE88C ; End of function sub_1DBE83C

Посмотрим что в параметрах у sub_1DBC554, что будет после:

Осталось разобрать sub_1DBC554 и sub_1DBCEF0 и дело сделано.

Пожалуй прервусь на этом этапе, функции достаточно объемные, если будет интерес то напишу 2ю часть )

p.s. Посмотрел на сайте http_s://www.support.xerox.com/en-us/content/121246, есть версия новее — 15.007.01.000, но переделывать всё не хочется, т.к. изменились адреса загрузки ядра, соответственно и все процедуры сдвинулись… Если есть желание можете пройти этот путь с новой прошивкой, думаю результат будет тот же.

ссылка на оригинал статьи https://habr.com/ru/articles/1064990/