LINUX.ORG.RU

Методика поиска аналогичного кода в бинарном файле нового релиза.

 , , , ,


0

1

Здравствуйте. Попала в руки такая задача. Есть две dll. Как мне объяснили второй файл (new.dll) это новый релиз первого файла (old.dll). Оба файла собраны под x64. Мне нужно найти во что реинкорнировали несколько функций из old.dll в new.dll. Ниже пример одной из функций. Прошу высказать мысли о моем подходе к поиску новой версии кода: Начал я с того, что при помощи rdare2 нашел все функции в old.dll (более 40 тыс), создал файл с сигнатурами и натравил на новый файл. В итоге ничего не нашлось. Делаю вывод, что изменения более чем косметические. Далее я решил искать следующим образом:

  1. Делаю поиск по кускам кода функции. Беру пролог перед вызовом функции и ищу эту последовательность байт в new.dll.
  2. Пытаюсь найти константы, строки и прочие магические цифры, которые фигурируют в функции и ищу их в new.dll.
  3. Анализирую все функции, которые вызывают нужную функцию и пытаюсь найти аналогичный набор вызывающих функций в new.dll.
  4. Определить последовательность вызывающих функций до самой первой (верхней) и найти аналогичную череду вызовов в новом файле.
  5. Анализирую все функции, которые вызываются из нужной функции и пытаюсь найти аналогичный набор вызываемых функций в new.dll
  6. Тут признаюсь, что все выше перечисленное мне не помогло. Далее думаю, что т.к. встречаются такие вызовы call qword ptr [rax+18h] (их штук 8 в анализируемой функции), то вероятно это вызовы методов объекта(-ов). Вероятно можно найти vftable и понять к какому классу эти методы относятся и уже составить набор класс.метод, которые вызываются в моей функции. Далее искать в new.dll где вызывается такая череда методов из соответствующих классов.
  7. Наверное можно попытаться найти где создавался объект и откуда этот this пришел в мою функцию. Далее искать аналогичный след в new.dll. Не уверен, что этот метод можно применить без отладки этой dll. Запускать dll не понятно как т.к. экспортируемых функций всего пять: Osf::OSFCreateOfficeExtensionsDialogUser Osf::OSFCreateOsfOartGallery DllGetLCID PPMain DllEntryPoint

Что из перечисленных подходов поиска утопия, а что нет? Может есть еще проверенные варианты?

Пример одной из функций:

.text:00000001806FFB30                               f1              proc near               ; CODE XREF: sub_1806F3630+172↑p
.text:00000001806FFB30                                                                       ; sub_1806FFC70+27↓p ...
.text:00000001806FFB30
pperrinfo        = qword ptr -260h
perrinfo          = qword ptr -258h
var_250         = qword ptr -250h
var_248         = dword ptr -248h
var_244         = qword ptr -244h
var_23C         = word ptr -23Ch
var_30          = qword ptr -30h
; __unwind { // __GSHandlerCheck
push    rbp
push    rbx
push    rsi
push    rdi
push    r14
lea      rbp, [rsp-160h] ; Load Effective Address
sub     rsp, 260h       ; Integer Subtraction
mov    rax, cs:__security_cookie
xor     rax, rsp        ; Logical Exclusive OR
mov    [rbp+180h+var_30], rax
mov    rbx, rcx
mov    esi, r8d
lea      rcx, [rsp+280h+pperrinfo] ; pperrinfo
mov    rdi, rdx
call     cs:CreateErrorInfo ; Indirect Call Near Procedure
xor     r14d, r14d      ; Logical Exclusive OR
test    eax, eax        ; Logical Compare
jns     short loc_1806FFB80 ; Jump if Not Sign (SF=0)
mov   ecx, 8B843h
call     Mso20Win32Client_1159 ; Call Procedure
jmp    loc_1806FFC52   ; Jump
; ---------------------------------------------------------------------------
loc_1806FFB80:                          ; CODE XREF: f1+3F↑j
mov   rdx, cs:qword_181031910
test    rdx, rdx        ; Logical Compare
jz       short loc_1806FFB9D ; Jump if Zero (ZF=1)
mov   rcx, [rsp+280h+pperrinfo]
mov   rdx, [rdx]
mov   rax, [rcx]
mov   rdx, [rdx]
call    qword ptr [rax+18h] ; Indirect Call Near Procedure
loc_1806FFB9D:                          ; CODE XREF: f1+5A↑j
mov     rcx, [rsp+280h+pperrinfo]
mov     rdx, rdi
mov     rax, [rcx]
call      qword ptr [rax+30h] ; Indirect Call Near Procedure
mov     rcx, [rsp+280h+pperrinfo]
mov     edx, esi
mov     rax, [rcx]
call      qword ptr [rax+38h] ; Indirect Call Near Procedure
mov     rcx, cs:qword_181038800
lea       rax, [rsp+280h+var_23C] ; Load Effective Address
mov     r9d, 100h
mov     [rsp+280h+var_250], rax
lea       r8, [rsp+280h+var_23C] ; Load Effective Address
mov     [rsp+280h+var_244], r9
mov     edx, 61850043h
mov     [rsp+280h+var_248], 1
mov     [rsp+280h+var_23C], r14w
call      Mso30Win32Client_27 ; Call Procedure
mov     rcx, [rsp+280h+pperrinfo]
add      eax, eax        ; Add
mov     rdx, [rsp+280h+var_250]
mov     dword ptr [rsp+280h+var_244+4], eax
mov     rax, [rcx]
call      qword ptr [rax+20h] ; Indirect Call Near Procedure
mov     rcx, [rsp+280h+pperrinfo]
mov     rdx, rbx
mov     rax, [rcx]
call      qword ptr [rax+28h] ; Indirect Call Near Procedure
mov     rcx, [rsp+280h+pperrinfo]
lea       r8, [rsp+280h+perrinfo] ; Load Effective Address
lea       rdx, unk_180C909A8 ; Load Effective Address
mov     rax, [rcx]
call      qword ptr [rax] ; Indirect Call Near Procedure
test      eax, eax        ; Logical Compare
js         short loc_1806FFC47 ; Jump if Sign (SF=1)
mov     rdx, [rsp+280h+perrinfo] ; perrinfo
xor      ecx, ecx        ; dwReserved
call      cs:SetErrorInfo ; Indirect Call Near Procedure
mov     rcx, [rsp+280h+perrinfo]
mov     rax, [rcx]
call      qword ptr [rax+10h] ; Indirect Call Near Procedure
loc_1806FFC47:                          ; CODE XREF: f1+FD↑j
mov     rcx, [rsp+280h+pperrinfo]
mov     rax, [rcx]
call      qword ptr [rax+10h] ; Indirect Call Near Procedure
loc_1806FFC52:                          ; CODE XREF: f1+4B↑j
mov     rcx, [rbp+150h]
xor      rcx, rsp        ; Logical Exclusive OR
call      sub_1801BFAE0   ; Call Procedure
add     rsp, 260h       ; Add
pop     r14
pop     rdi
pop     rsi
pop     rbx
pop     rbp
retn                    ; Return Near from Procedure
; } // starts at 1806FFB30
f1              endp

И нафига тут кому-либо твой пример?

Когда-то я писал дизассемблер и декомпилятор и вот на этой задаче зарылся.

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

Наконец нужно как-то нечетко сравнить графы от одной и другой функции и вот это задача на миллион. Всё вышеописанное - это рутина. А сравнение нужно и для декомпиляции, чтоб узнавать заинлайненые функции.

Так вот, то что ты хочешь - это задача аналогичная вышеописанной, разве что не текст на С++ генерируется, а нечто другое. Существующие декомпиляторы - штуки довольно хромые а на них убили кучу времени и материальных средств.

Ты точно уверен что тебе здесь помогут забесплатно, или даже за платно?

salozar ()
Ответ на: комментарий от Eddy_Em

Т.е. по-твоему, лучше быть вантузоидом, чем линуксоидом?

Это не важно, важно что ты решаешь свои задачи.

Какой из тебя ЛОРовец?

Сначала ответь себе на вопрос, а кто такой ЛОРовец?

Если бы ЛОР был ресурсом исключительно про линукс, а не возле, да около, то тогда можно было бы задавать подобные вопросы. Почему-то на узко-специализированные форумы посторонних не тянет. Этот аспект обсуждался неоднократно, сколько помню, года с 2003-го.

anonymous ()
Ответ на: комментарий от anonymous

Если бы ЛОР был ресурсом исключительно про линукс

Исключительно про линукс и BSD. На главной же написано: «русская информация об ОС Linux».

Соответственно, вменяемым модераторам нужно это учитывать и удалять всякие мако-вендузяческие темы и сообщения. И проприетарщину стоит загнать в определенную песочницу, чтобы эта дрянь оттуда не вылезала.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

вменяемым модераторам нужно это учитывать и удалять всякие мако-вендузяческие темы и сообщения. И проприетарщину стоит загнать в определенную песочницу, чтобы эта дрянь оттуда не вылезала.

т.е. ЛОР ты ненавидишь?

anonymous ()
Ответ на: комментарий от Eddy_Em

С каких пор в линуксе есть «dll»

с тех самых, когда люди на нём работать начали, а не стонать про божественную КОИ-8 и засилие systemd
сурслист тебе специально, иначе опять плакать и бред нести начнёшь про нехаляльность дистрибутива.

sudo find /opt/ -name *.dll|wc -l && grep deb /etc/apt/sources.list
181
# deb cdrom:[Debian GNU/Linux 10.2.0 _Buster_ - Official amd64 NETINST 20191116-09:56]/ buster main
#deb cdrom:[Debian GNU/Linux 10.2.0 _Buster_ - Official amd64 NETINST 20191116-09:56]/ buster main
deb http://deb.debian.org/debian/ buster main
deb-src http://deb.debian.org/debian/ buster main
deb http://security.debian.org/debian-security buster/updates main
deb-src http://security.debian.org/debian-security buster/updates main
deb http://deb.debian.org/debian/ buster-updates main
deb-src http://deb.debian.org/debian/ buster-updates main
# (e.g. netinst, live or single CD). The matching "deb cdrom"

novitchok ★★★★★ ()
Последнее исправление: novitchok (всего исправлений: 1)
Ответ на: комментарий от novitchok

Ну и что ты мне своей мастдайкой тычешь здесь (или в твоем дебиане sysvinit/openrc?)? Я уверен на все 100%, что ты в /opt поставил wine или еще какое ненужное Г. А то и вовсе на до-диезе пописываешь, как рядовой вендузоид...

P.S. зачем тебе sudo для выполнения операции find? Вылитый вендузятник!

Eddy_Em ☆☆☆☆☆ ()
Последнее исправление: Eddy_Em (всего исправлений: 2)
Ответ на: комментарий от novitchok

Я готов поставить сто рублей, что ты - вендузятник, поэтому у тебя там дллки и валяются.

Покажи хоть первые 7 штук из списка!

Eddy_Em ☆☆☆☆☆ ()
Последнее исправление: Eddy_Em (всего исправлений: 1)
Ответ на: комментарий от Eddy_Em

зачем тебе sudo для выполнения операции find? Вылитый вендузятник!

ну как бы тебе это проще объяснить, дорогой ты наш городской сумасшедший, мне проще финд из-под рута именно в данном случае, sudo - четыре символа, а 2>/dev/null - одиннадцать, зачем мне читать, что у меня доступа к /opt/lost+found нет? прикинь, опт отдельным разделом монтируется, а, я забыл, ты же у нас этот, как его. ну ты понел.

novitchok ★★★★★ ()
Ответ на: комментарий от novitchok

Вендузятник, ты бы помалкивал...

прикинь, опт отдельным разделом монтируется

Делать тебе нечего, как я вижу!

В /opt вообще пусто должно быть у нормального линуксоида!!!

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

А то и вовсе на до-диезе пописываешь, как рядовой вендузоид…

Что ещё за до-диез? Если ты имеешь ввиду C# и .Net то чем они тебе не нравятся в linux? Лицензионно они даже чище последних версий жабки сейчас.

anonymous ()
Ответ на: комментарий от Eddy_Em

Покажи хоть первые 7 штук из списка!

 $ (dir $PSHOME\*.dll -Recurse)[0..6].Name
Microsoft.CodeAnalysis.CSharp.resources.dll
Microsoft.CodeAnalysis.resources.dll
Microsoft.VisualBasic.Forms.resources.dll
PresentationCore.resources.dll
PresentationFramework.resources.dll
PresentationUI.resources.dll
ReachFramework.resources.dll
anonymous ()

Глянь на гугловский проект

https://www.chromium.org/developers/design-documents/software-updates-courgette

Этой штукой они раньше (а может и до сих пор) обновляют хромиум. Вместо полного скачивания всего приложения каждый раз, они умеют находить именно небольшие реальные изменения в исполняемых бинарниках. Причем, верно умеют работать с изменившимися адресами.

Я им не пользовался, но, судя по описанию, идеально тебе подходит.

anonymous ()
Ответ на: комментарий от static_lab

Я в терминале при необходимости и логинюсь. Но если я в иксах, то нужно делать su -l. А sudo у меня настроено без пароля и строго на выполнение mount/umount и poweroff:

root ALL=(ALL) ALL
ALL ALL=(ALL) NOPASSWD: /bin/ntfs-3g,/bin/mount,/bin/umount
eddy ALL=(ALL) NOPASSWD: /sbin/poweroff
homyak ALL=(ALL) NOPASSWD: /sbin/poweroff
eddy ALL=(homyak) NOPASSWD: /usr/bin/google-chrome-stable
Eddy_Em ☆☆☆☆☆ ()