Otázka:
Táhne mi IDA nohu - nebo to REX.W někdy nelze určit statickou analýzou?
0xC0000022L
2018-07-05 19:16:52 UTC
view on stackexchange narkive permalink

Pozn .: Normálně se zabývám demontáží (tj. mnemotechnickými pomůckami) a vždy se dívám pouze na surové operační kódy, když se jim nemohu vyhnout.

Mám následující řádek demontáže režimu jádra Windows x64 ovladač, vytvořený IDA Pro 7.1.180227:

  xor edx, edx  

Nyní vím o tom, že toto je v přípravě předání druhého parametru funkci přes rdx . Také vím, že záměrem tohoto kódu je nastavit uvedený argument ukazatele na NULL.

Opcode je 33 D2 . A křížové odkazy, které s odkazem nebo jeho prohlížením v ODA, přinesou to samé jako u IDA: xor edx, edx .

To, co mě na této demontáži svádí špatně, je to, že rdx , jako nadmnožina edx , se používá jinde na této přesné cestě kódu k ukládání dalších ukazatelů. Teoreticky by tedy horní dvojslovo rdx mohlo být „špinavé“.

A vzhledem k tomu, že se jedná o kód x64, očekával bych, že bude číst xor rdx, rdx . Proč tomu tak není při demontáži?


Nyní chápu, že podle oddílu 3.6.1 (tabulka 3-4) Intel SDM ( 05/2018) předpona REX.W operačního kódu může ovlivnit velikost operandu.

U tohoto operačního kódu není k dispozici předpona velikosti operandu (66h) ani předvolba velikosti adresy (67h).

Takže pokud jde o Intel SDM (část „XOR — Logical Exclusive OR“), měl bych se skutečně zabývat opcode 33 / r nebo instrukcí XOR r32, r / m32 , což potvrzuje překlad IDAs operačního kódu. Odkaz na oddíl 2.1.5 („Kódování režimu adresování ModR / M a SIB bajtů“) Intel SDM nám dává představu o tom, jak je operand ( D2 ) kódován, a tak nám dává , z tabulky 2-2 („32bitové adresovací formuláře s modulem ModR / M Byte“): EDX / DX / DL / MM2 / XMM2 jako operand.

Obrázky.

To by však znamenalo, že „špinavé“ horní dvojslovo v rdx by nebylo vynulováno a tudíž by byl předán poškozený / zkrácený ukazatel. Vzhledem k tomu, že se jedná o kód režimu jádra, důsledky by měly být jasné.

Nemůžu uvěřit, že by kompilátor udělal takovou chybu. Co mi chybí ?

Můžete zahrnout nějaký související kód? řekněme, kód používající E / RDX, další kód, který s ním manipuluje před instrukcí XOR atd. Nedávno jsem narazil na podobný problém, kdy po nějakém důkladnějším prozkoumání byla horní polovina RDX skutečně vždy nulová, což z něj dělá nevyužitelnou chybu vývojář.
duplicate of stackoverflow [Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?](https://stackoverflow.com/q/11177137), and see also [What is the best way to set a register to zero in x86 assembly: xor, mov or and?](https://stackoverflow.com/q/33666617) which explains that 32-bit operand-size is always best (e.g. `xor r10d, r10d` is not shorter than `xor r10,r10`, but Silvermont only recognizes 32-bit operand size as a zeroing idiom!)
Jeden odpovědět:
jakobbotsch
2018-07-05 19:31:07 UTC
view on stackexchange narkive permalink

V x86-64 každá operace, která ovlivňuje pouze dolních 32 bitů registru, automaticky vynuluje horních 32 bitů.

Příslušná část příručky k architektuře Intel je ve svazku 1, 3.4. 1.1, který uvádí:

V 64bitovém režimu určuje velikost operandu počet platných bitů v cílovém univerzálním registru:

  • 64- bitové operandy vygenerují 64bitový výsledek v cílovém univerzálním registru.
  • 32bitové operandy vygenerují 32bitový výsledek s nulovým rozšířením na 64bitový výsledek v cílovém obecném -účelový registr.
  • 8bitové a 16bitové operandy generují 8bitový nebo 16bitový výsledek. Horní 56 bitů nebo 48 bitů (v uvedeném pořadí) cílového registru pro všeobecné účely se operací nemění. Pokud je výsledek 8bitové nebo 16bitové operace určen pro výpočet 64bitové adresy, výslovně podepište a rozšířte registr na celých 64 bitů.

Obě formy tedy dávají stejný výsledek a xor edx, edx je o jeden bajt kratší než xor rdx, rdx , takže jej kompilátor upřednostňuje.

Mimochodem, to také dává další složitosti. Například instrukce NOP je obvykle 0x90, což je ve skutečnosti `xchg eax, eax`. Ale v 64bitovém režimu to není NOP, protože to vynuluje horních 32 bitů. Program `xchg eax, eax` má tedy v 64bitovém a 32bitovém režimu různá kódování.
Někde jsem o tom četl, ale spojení jsem nenavázal.
AilicccrseCMT I believe opcode 0x90 is always handled as `nop` in all modes. It does not clear top part of `rax`.
@IgorSkochinsky Ano, to jsem měl na mysli. Museli najít nové kódování pro `xchg eax, eax`, protože by to nebyl NOP na x64.
AilitghypiCMT Where's the issue? xchg eax, eax already had two encodings.
AilinaulkcCMT Right, I think what Jakob meant to say is that *assemblers* can't use the `0x90` short form for `xchg eax,eax` in the asm source, and have to use the `xchg r, r/m32` form with a ModRM byte (http://felixcloutier.com/x86/XCHG.html). But fun fact, 16 and 64-bit operand sizes can still use `0x90` with a 66 or REX.W prefix. NASM does assemble `xchg ax,ax` to `66 90` in 64-bit mode.
@PeterCordes Přesně. Zformuloval jsem to špatně, ale nakonec jsme se tam dostali!


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 4.0, pod kterou je distribuován.
Loading...