SaeLog #8: Aplikowanie zmian do kodu programu
• tech • 640 słów • 4 minuty czytania
Ta notatka jest częścią serii Saleae Logic Hack. Zapoznaj się z pozostałymi wpisami.
W wolnych chwilach pracowałem nad funkcjonalnością patchowania plików w moim projekcie strzykawki - syringe. Funkcja ta ukazała się pod postacią komendy patch
. Nie tylko potrafi ona nakładać IDA-owe pliki diff na standardowe binarki, ale także, co było dla mnie ważne, bezpośrednio na dane zapisane w formacie IntelHex. Takiej możliwości potrzebowałem, aby móc dokończyć całą zabawę z analizatorem logicznym Saleae Logic i finalnie zaaplikować wszystko do programu. A ostatecznie rownież wygenerować łatkę rozwiązującą problem.
Generowanie pliku diff dla firmware
Plik dif wygenerowany przez IDA-e, z modyfikacjami kodu firmware jakie wcześniej dokonałem (SaeLog #6 i SaeLog #7) mogę w łatwy sposób nałożyć na oryginalny kod zapisany w pliku hex. Wystarczy użyć polecenia patch
:
syringe patch -f IDA --target "Intel Hex" C:\SaeLog\firmware.hex C:\SaeLog\firmware.dif
Porównując wynikowy plik zawierający zmodyfikowany kod z oryginalnym plikiem hex, przy pomocy jakiegoś rodzaju narzędzia typu diff/merge, będzie możliwe stworzenie typowego diff-a. Taki standardowy plik zmian w bardziej ludzki sposób przedstawi zmiany jakie zaszły w pliku hex, a także będzie służył wielką pomocą przy modyfikacji programu Logic.exe.
Mój diff prezentuje się następująco:
--- C:/SaeLog/firmware_org.hex Pt 2015-12-11 21:07:56
+++ C:/SaeLog/firmware.hex Pt 2015-12-11 21:08:22
@@ -323,13 +323,13 @@
:02159800D3225C
:02159A00C3226A
:100D74008F598D5A90E678E0FFEF4480FF90E67833
-:100D8400EFF090E67974A0F090E678E0FFEF30E0C1
-:100D9400F790E678E0FFEF20E11B90E678E0FFEFC4
+:100D8400EFF07400120B300090E678E0FFEF30E0F3
+:100D9400F790E678E0FFEF20E13B90E678E0FFEFA4
:100DA4004440FF90E678EFF090E678E0FFEF30E61D
:100DB400C380F580BF90E679E55AF090E678E0FFCD
-:100DC400EF30E0F790E678E0FFEF20E11B90E67863
-:100DD400E0FFEF4440FF90E678EFF090E678E0FF24
-:100DE400EF30E69080F5808C90E679E559F090E656
+:100DC400EF30E0F790E678E0FFEF30E1CDE55A70E0
+:100DD400178D5A80E090E678E030E405AD5A755AF4
+:100DE4000080D29080F5808C90E679E559F090E609
:100DF40078E0FFEF30E0F790E678E0FFEF20E11FC6
:100E040090E678E0FFEF4440FF90E678EFF090E65C
:100E140078E0FFEF20E603020D7880F2020D78906F
@@ -337,15 +337,15 @@
:0D0E3400E0FFEF30E60680F522020D782287
:0809FB008F428B438A448945B9
:100A0300AB43AA44A9458B478A48894990E678E0D5
-:100A1300FFEF4480FF90E678EFF090E67974A0F062
+:100A1300FFEF4480FF90E678EFF07400120B300094
:100A230090E678E0FFEF30E0F790E678E0FFEF2024
-:100A3300E11B90E678E0FFEF4440FF90E678EFF0AB
+:100A3300E13B90E678E0FFEF4440FF90E678EFF08B
:100A430090E678E0FFEF30E6C380F580BF90E6796B
:100A5300E542F090E678E0FFEF30E0F790E678E0EB
-:100A6300FFEF20E11B90E678E0FFEF4440FF90E6C4
-:100A730078EFF090E678E0FFEF30E69080F5808C39
-:100A830090E678E0FFEF4480FF90E678EFF090E6A1
-:100A93007974A1F090E678E0FFEF30E0F790E67824
+:100A6300FFEF30E1CDE542701A8B4280E090E678EB
+:100A7300E030E405AB4275420080D29080F5808C73
+:100A830090E678E0FFEF4480FF90E678EFF07401A2
+:100A9300120B300090E678E0FFEF30E0F790E67855
:100AA300E0FFEF20E11F90E678E0FFEF4440FF9086
:100AB300E678EFF090E678E0FFEF20E603020A0F16
:100AC30080F2020A0F90E679E0FF8F4A90E678E021
@@ -354,9 +354,9 @@
:100AF30090E678EFF090E679E0FFAB47AA48A94982
:100B0300EF120FFE74012549F549E43548F5489085
:100B1300E678E0FFEF30E0F790E678E0FFEF20E1E2
-:100B230028E54614FFEF654A601F90E678E0FFEF83
-:100B33004440FF90E678EFF090E678E0FFEF20E6A0
-:100B430003020A0380F2020A03054A808B90E678C7
+:100B230028E54614FFEF654A601F020A3524A0FF3B
+:100B330090E678E030E404EF2402FFEF90E679F0EA
+:100B430022020A0380F2020A03054A808B90E678A8
:100B5300E0FFEF4440FF90E678EFF090E678E0FFA7
:0A0B6300EF30E60680F522020A0FCB
:010B6D002265
Zmianie uległo tylko (a może aż 14) linii, ale gdy przyjrzymy się bliżej to będzie to tylko 91 bajtów, jakie zawierała oryginalna latka + zaktualizowane checksumy.
Generowanie patcha dla logic.exe
Wiem już które linie w reprezentacji IntelHex firmware ulegają zmianie, więc bez problemu mogę je zlokalizować w sekcji .rdata
pliku wykonywalnego aplikacji. Poniżej odpowiednio adres, offset w pliku i zmienione dane, jakie powinny znaleźć się pod podanym adresem:
00CE2518 008E0B18 :100D8400EFF07400120B300090E678E0FFEF30E0F3
00CE24EC 008E0AEC :100D9400F790E678E0FFEF20E13B90E678E0FFEFA4
00CE2468 008E0A68 :100DC400EF30E0F790E678E0FFEF30E1CDE55A70E0
00CE243C 008E0A3C :100DD400178D5A80E090E678E030E405AD5A755AF4
00CE2410 008E0A10 :100DE4000080D29080F5808C90E679E559F090E609
00CE22C4 008E08C4 :100A1300FFEF4480FF90E678EFF07400120B300094
00CE226C 008E086C :100A3300E13B90E678E0FFEF4440FF90E678EFF08B
00CE21E8 008E07E8 :100A6300FFEF30E1CDE542701A8B4280E090E678EB
00CE21BC 008E07BC :100A7300E030E405AB4275420080D29080F5808C73
00CE2190 008E0790 :100A830090E678E0FFEF4480FF90E678EFF07401A2
00CE2164 008E0764 :100A9300120B300090E678E0FFEF30E0F790E67855
00CE1FD8 008E05D8 :100B230028E54614FFEF654A601F020A3524A0FF3B
00CE1FAC 008E05AC :100B330090E678E030E404EF2402FFEF90E679F0EA
00CE1F80 008E0580 :100B430022020A0380F2020A03054A808B90E678A8
Takie dane są wystarczające do napisania prostego programu lub skryptu modyfikującego plik aplikacji. A jeśli syringe może aplikować patche z IDA, to najłatwiej byłoby pokusić się jednak o wygenerowanie takowych plików. Mogłoby to ułatwić zastosowanie finalnych modyfikacji zainteresowanym użytkownikom. Ale, że nie bardzo chciało mi się przyklepywać zmodyfikowane dane, to sobie walnąłem prosty skrypt w perlu:
#!/usr/bin/perl
use strict;
use warnings;
my $source = 'logic.patch';
my $target = 'logic.exe';
open SH, '<', $source or die "Open file '$source' failed: $!";
open TH, '+<', $target or die "Open file '$target' failed: $!";
binmode(TH);
while (<SH>) {
my @rec = split(/\t/);
my $pos = hex($rec[1]);
chomp ($rec[2]);
print "Writting data at $pos\n";
seek TH, $pos, 0 or die "Seek failed: $!";
print TH $rec[2] or die "Write failed: $!";
}
close TH or die "Close file '$target' failed: $!";
close SH or die "Close file '$source' failed: $!";
Teraz wystarczy odpalić skrypt, aby zmiany zostały wprowadzone w pliku programu. Można pokusić się o wpakowanie jako tablicy zawartości pliku logic.patch
do skryptu, wtedy cały skrypt można traktować jako typowy patch.
Należy mieć na uwadze, że wszystkie zmiany jakie dokonywałem dotyczą wersji firmware z jaką moje urządzenie wchodziło w interakcje. Aplikacja ma zaszyte kilka wersji firmware, w którejś z części (chyba przy ekstrakcji kodu firmware z aplikacji) o tym pisałem.
Dzięki temu, że starałem się nie zwiększać kodu firmware, ale modyfikować tylko istniejący kod i upychać nowe instrukcje, aplikowanie do programu jest proste. Gdybym zwiększył kod urządzenia, wtedy sprawa byłaby trochę bardziej skomplikowana. Musiałbym gdzieś upchać nowe linie/dane kodu w IntelHex, np. w wolnych przestrzeniach, modyfikować funkcje związane z ładowaniem danych z .rdata
do pamięci i inne… mówiąc prosto, dużo więcej zabawy.
Zpatchowany program powinien działać bez zarzutu ;)
Komentarze (0)