Otázka:
převést tento x86 ASM na C?
user1365830
2013-05-26 00:15:24 UTC
view on stackexchange narkive permalink

Jak by mohla být tato 32bitová sestava x86 napsána v jazyce C?

  loc_536FB0: mov cl, [eax] cmp cl, '' jb short loc_536FBCcmp cl, ',' jnz short loc_536FBFloc_536FBC : mov byte ptr [eax], '' loc_536FBFmov cl, [eax + 1] inc eaxtest cl, cljnz short loc_536FB0  

Už jsem zjistil, že jde o smyčku for, která smyčky 23 krát před ukončením.

čtyři odpovědi:
Igor Skochinsky
2013-05-26 01:11:41 UTC
view on stackexchange narkive permalink

Takové malé úryvky nejsou příliš těžké na ruční dekompilaci. Zkusme to.

Už jste zjistili, že cl obsahuje znak, to znamená, že eax , ze kterého se čte, je ukazatel na znak pole. Říkejme tomu p . Nyní udělejme hloupý překlad pro každý výpis sestavy do C:

  l1:; 11: mov cl, [eax]; cl = * p; cmp cl, ''; if (cl < '') jb short l2; přejít na l2cmp cl, ','; if (cl! = ',') jnz short l3; přejít na l3l2:; l2: mov byte ptr [eax], ''; * p = '' l3:; l3: mov cl, [eax + 1]; cl = * (p + 1) včetně eax; p = p + 1test cl, cl; if (cl! = 0) jnz short l1; přejít na l1  

A vyčistit:

  l1: cl = * p; if (cl < '') goto l2; if (cl! = ',') goto l3; l2: * p = ''; l3: cl = * (p + 1); p = p + 1; if (cl! = 0) goto l1;  

Nyní se podívejme na druhý if . Má následující podobu:

  if (podmínka) goto end_of_if; <if body>end_of_if:  

A tady je návod, jak se můžeme zbavit goto:

  if (! Podmínka) {<if body> }  

Použití na náš fragment:

  l1: cl = * p; if (cl < '') goto l2; if (cl == ',') {l2: * p = ''; } cl = * (p + 1); p = p + 1; if (cl! = 0) goto l1;  

Jak se můžeme zbavit goto l2 ? Pokud se na to podíváte pečlivě, uvidíte, že tělo na l2 bude provedeno, pokud buď cl < '' nebo cl == ',' . Můžeme tedy jen kombinovat dvě podmínky s logickým OR ( || ):

  l1: cl = * p; if (cl < '' || cl == ',') {* p = ''; }
cl = * (p + 1); p = p + 1; if (cl! = 0) goto l1;  

Nyní nám zbývá jeden goto . Máme: 1) štítek na začátku bloku výpisu 2) kontrola na konci bloku a 3) přechod na začátek bloku, pokud kontrola proběhla úspěšně. Toto je typický vzor smyčky do-while a můžeme jej snadno převést:

  do {cl = * p; if (cl < '' || cl == ',') {* p = ''; } cl = * (p + 1); p = p + 1; } while (cl! = 0)  

Nyní je kód téměř pěkný a hezký, ale můžeme ho komprimovat o něco více nahrazením ekvivalentních příkazů:

  do {if (* p < '' || * p == ',') * p = ''; cl = * ++ p;} while (cl! = 0)  

A nakonec lze poslední podmínku přesunout do podmínky:

  do {if (* p < '' || * p == ',') * p = '';} while (* ++ p! = 0)  

Nyní je to zřejmé co kód dělá: prochází řetězcem a nahrazuje všechny speciální znaky (ty s kódy menšími než 0x20 aka mezera) a čárkami mezerami.

Skvělá odpověď, zejména proto, že vysvětlujete každý krok.
Fantastická odpověď.
Sám jsem to nemohl udělat lépe
* čte odpověď * „Páni, to je opravdu podrobně informativní, zajímalo by mě, kdo ...“ * si uvědomuje, že je to ten člověk, který zpětně vytvořil Intel IME * „Ahhhhh ...“
Denis Laskov
2013-05-26 00:42:40 UTC
view on stackexchange narkive permalink

No, zvláště pro to byl vyvinut Dexpiler Hex-Rays. Bude dekompilovat ASM kód na pseudo-C a odtud můžete psát logiku C kódu sestavení, který máte.

vyřešil to teď
ne každý má přístup k hexadecimálním paprskům ... Igorova odpověď je mnohem důkladnější.
Ne každý má malý kousek shromáždění, takže odpověď by měla být širší než jeden konkrétní případ. A opravdu díky Igorovi za to, že strávil svůj drahocenný čas pro tento konkrétní kus kódu.
Ne, neodpověděl jsi na otázku. Chcete-li odkazovat na nástroj, díky kterému je otázka zastaralá, udělejte to v komentáři k otázce.
oh, promiň, maso :)
Věřím, že [Igor] (https://reverseengineering.stackexchange.com/users/60/igor-skochinsky) je vývojář pro Hex-Rays.
Tox1k
2013-05-26 02:23:39 UTC
view on stackexchange narkive permalink

Takto by to vypadalo ve zdroji. Fastcall je náhradou za vlastní konvenci listů, kterou kompilátor použil při optimalizaci.

  void __fastcall __forceinline RemoveControlChars (char * szInput) {int i; for (i = 0; i < 23 && * szInput; ++ i, ++ szInput) {if (* szInput < '' || * szInput == ',') * szInput = ''; }}  
V původním kódu není nic, co by odpovídalo vašemu stavu pokračování `i <24`. Počínaje i = 0 a smyčkování, zatímco i <24, provede smyčku také 24krát, ne 23, jak uvádí OP.
fastcall a forceinline dohromady nedávají žádný smysl. Pokud je to podtrženo, neexistuje žádná formální konvence volání.
__fastcall jednoduše znamená, že args budou předávány v registrech namísto na zásobníku, což se předpokládá, pokud je vloženo, ale kompilátor může stále tlačit args na zásobník, pokud není dostatek registrů, což je jakousi hackerskou anti-optimalizací. Podle msdn: `I při __forceinline kompilátor nemůže za všech okolností vložit kód .`
Not Star
2020-08-29 16:17:45 UTC
view on stackexchange narkive permalink

Můžete použít r2dec plugin na radare2 s příkazem pdda

  [0x08048060] > pdda; montáž | / * výstup pseudo kódu r2dec * / | / * ret @ 0x8048060 * / | #include <stdint.h> | ; (fcn) entry0 () | int32_t entry0 (void) {| dělat {| / * [01] -r-x velikost sekce 23 s názvem .text * / 0x08048060 mov cl, byte [eax] | cl = * (eax); 0x08048062 cmp cl, 0x20 | | if (cl > = 0x20) {0x08048065 jb 0x804806c | 0x08048067 cmp cl, 0x2c | | if (cl! = 0x2c) {0x0804806a jne 0x804806f | přejít štítek_0; | } | } 0x0804806c mov byte [eax], 0x20 | * (eax) = 0x20; | label_0: 0x0804806f mov cl, byte [eax + 1] | cl = * ((eax + 1)); 0x08048072 včetně eax | eax ++; 0x08048073 testovací cl, cl | 0x08048075 jne 0x8048060 | | } while (cl! = 0); | } [0x08048060] >  


Tyto otázky a odpovědi byly automaticky přeloženy z anglického jazyka.Původní obsah je k dispozici na webu stackexchange, za který děkujeme za licenci cc by-sa 3.0, pod kterou je distribuován.
Loading...