[gdb] podmiana funckji w trakcie debugowania

[gdb] podmiana funckji w trakcie debugowania
nullpt4
  • Rejestracja:prawie 6 lat
  • Ostatnio:5 miesięcy
  • Postów:103
0

Cześć,
kojarzy ktoś czy można jakoś podmienić funkcje w gdb?

cos w stylu

Kopiuj
(gdb) print exit
$5 = {<text variable, no debug info>} 0xf6b777a0 <exit>
(gdb) whatis exit
type = <text variable, no debug info>
(gdb) print sleep
$6 = {<text variable, no debug info>} 0xf76daa4b <sleep>
(gdb) set *0xf6b777a0=0xf76daa4b

EDIT:
przykładowy kod

Kopiuj
void foo() {
   std::cout << "hello" << std::endl;
   sleep(1);
   exit(1);
   std::cout << "hello" << std::endl;
   return;
}

chciałbym jakoś pozbyć się tego exit by funkcja wypisała hello\nworld i pomyślałem,
że jak przypisze adresowi funcji exit inną funckcję (np. sleep) to pozbędę się exit'a.
ale set *0xf6b777a0=0xf76daa4b nie zadziałał ;/

edytowany 2x, ostatnio: nullpt4
Zobacz pozostałe 2 komentarze
nullpt4
kurde, sorry. już dopisuje
CC
Masz kilka opcji: 1 - mozesz uzyc atexit, 2. mozesz w gcc uzyc przelacznika -Dexit=new_handler_name, 3. mozesz uzyc LD_PRELOAD. Przy atexit bedziesz musial uzyc sigsetjmp, przy -Dexit musisz miec dostep do zrodel, przy opcji nr 3 nie mozesz byc na macOS. To jest mega nie halo, ale czasami jest to konieczne, gdy uzywa sie bibliotek zewnetrznych (np. w Fortranie) gdzie developerzy uwielbiaja robic sobie stop w srodku kodu.
Shalom
Z tego wszystkiego najbardziej uniwersalna opcja to LD_PRELOAD bo pozwoli nadpisywać dowolny symbol z shared library, ale znów, dla funkcji które są linkowane statycznie to juz nie pójdzie.
CC
Dodatkowo, w macOS mozna o tej opcji zapomniec :( Od (nie pamietam juz ktorej wersji) system na to nie pozwala.
nullpt4
@cCcCc: +1 dzięki!
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

Takie nadpisanie to mógłbyś zrobic jakbyś skompilował to bez RELRO, bo teraz pewnie masz GOT które jest read-only i nie da się tego adresu nadpisać. Zresztą i to miałoby sens tylko dla funkcji z jakiejś biblioteki dynamicznej, tak że adres jest resolvwowany później. Dla wielu funkcji adres będzie przecież inline w kodzie, a .text też sobie nie możesz nadpisać żeby zmienić kod.

Napisz może jednak co chcesz osiągnąć, bo to co robisz jest bardzo dziwne.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Zobacz pozostałe 2 komentarze
nullpt4
@Shalom: podesłabyś komendę którą moge przeskoczyć tego exita? jakoś nie mogę jej szybko wygooglować ;/ poleciłbyś też jakieś materiały które by mi pomogły ogarnąc np. spatchowanie i wynopowanie exita z binarki? :D
Shalom
Otwierasz biarkę w hexedytorze. Znajdujesz calla. Nopujesz. Ewentualnie robisz to samo za pomocą Ghidry, IDY czy jakiegoś x64dbg. Z debugera możesz po prostu zrobić jump adres albo set $pc=adres
AF
@Shalom a .text też sobie nie możesz nadpisać żeby zmienić kod To Linux nie umie w copy on write? To jak on w takim razie robi breakpoint w takim miejscu, przecież normalnie robiło się to przez modyfikowanie kodu i wstawienie int 3 w danym miejscu, więc skoro dało się wstawić int 3, to równie dobrze mógłbym z debuggera wstawić nopy. A jak się nie da, to kto tego blokuje i jak (bo x86 normalnie na to pozwala)?
Shalom
@Afish: nie no jasne że mozesz sobie odpalić gdb z --write albo wykonać set write on ale tak z buta jak autor chciał to nie bo takie opcje nie są domyślnie odpalone ;) Szczególnie że w 99% przypadków ktoś by coś popsuł :D
AF
Okej, dzięki.
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
2
nullpt4
dzięki za link, spróbuje ogarnać :D
nullpt4
  • Rejestracja:prawie 6 lat
  • Ostatnio:5 miesięcy
  • Postów:103
0

@Shalom: dzięki za jump'a! Sprawdziłem kilka scenariuszy i faktycznie udało mi się przeskoczyć wywoałnie zwykłej funkcji b +1; jump +1,
ale jeśli ta funckja to exit to tak jakby kod który jest po exit jest wycinany i nie ma go w binarce, nie można do niego skoczyć ;/
Kojarzysz czy można to jakoś obejść?
Kompiluje komendą g++ -O0 -g main.cpp

Kopiuj
#include <iostream>
#include <unistd.h>
 
void boo(int a) {
    std::cout << "boo" << std::endl;
 
}
 
void foo() {
    std::cout << "hello" << std::endl;
    sleep(1);
    exit(1); // with boo(); I can jump over it, but with exit() I cannot
    std::cout << "world" << std::endl; // this line is not available when previous line calls exit function
    return ;
}
 
int main(int argc, char *argv[]) {
    foo();
    std::cout << "after foo" << std::endl;
 
    return 0;
}

EDIT: dodaje output z gdb

Kopiuj
->  12       exit(1); // with boo(); I can jump over it, but with exit() I cannot
     13      std::cout << "world" << std::endl; // this line is not available when previous line calls exit function
     14      return ;
     15  }
     16
     17  int main(int argc, char *argv[]) {
------------------------------------------------------------------
gef> b +1
Breakpoint 2 at 0x4008af: file main.cpp, ******line 18.******

break jest ustawiany na lini 18'tej podczas gdy powinien być na 13'tej.

edytowany 3x, ostatnio: nullpt4
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2

No ciężko trochę, bo dead code zwykle po prostu wylatuje z binarki i tyle. Obawiam sie że może być trudno temu zapobiec. Popatrz sobie na godbolta albo deasembluj binarkę i zobaczysz co faktycznie "zostaje" w kodzie.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
nullpt4
a no tak, zły przykład podałem w sumie, powinienem dodać jakiegoś if'a który by był true/false w zależności od inputu użytkownika, wtedy mógłbym użyć jump'a bez problemu. Dzięki wszystko się wyjaśniło!
SL
W tym wypadku kompilator nie usunie kodu bo funkcja nie jest static. Musiałbyś odpalic kompilację z flagą -fwhole-program lub -flto
AL
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 3 lata
  • Postów:1493
2

To jest trochę szeroki temat z tym usuwaniem dead code'u. Możesz kombinować z -fno-dce i podobnymi, jednakże: https://stackoverflow.com/a/39835400/4885321
Exit jest funkcją o tyle specyficzną, że jest ona (z reguły) explicite oznaczona jako "noreturn", więc kompilator dostaje jasną informację, że potem ma już nic nie być.

Zobacz pozostałe 4 komentarze
AL
@Shalom: no spoko, ale na moje - skoro musi rekompilować to w RE to średnio pomoże. ;) Chyba, że to czysto dydaktyczne zabawy, to spoko ;)
nullpt4
@Shalom: no myśle że to może być pierwszy krok, bo mi się spodobało :D
AL
@nullpt4: ja bym zawrapował tego exita w makro czy jakiegoś static inline'a, po co tak się męczyć?
nullpt4
exitów jest dużo, nie chciałbym wszystkich wywalać, ani rekompilować kodu, a nawet jeśli bym się pozbył wszystkich exitów, to mogło by wyskoczyć coś innego (e.g. abort, długi sleep, etc.) i umiejętność przeskoczenia niechcianej linijki wydaje mi się bardzo przydatna i użyteczna :D robie b +1, jump +1 i po problemie :P
AL
@nullpt4: a to jasne. Z mojej strony jednak polecam wrapowanie ;)
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)