📄 macros.s
字号:
// =============.macro reloc32 buffer, destination, addvaluesection RELOC320reloc_main: xor eax, eax mov al, [\buffer] inc \buffer or eax, eax jzs reloc_endx cmp al, 0xEF ja reloc_fxreloc_add: add \destination, eax#if 1 mov eax, [\destination] xchg ah, al rol eax, 16 xchg ah, al add eax, \addvalue mov [\destination], eax#else add [\destination], \addvalue#endif jmps reloc_mainreloc_fx: and al, 0x0F shl eax, 16 mov ax, [\buffer] add \buffer, 2section REL32BIG or eax, eax jnzs reloc_add mov eax, [\buffer] add \buffer, 4section RELOC32J jmps reloc_addreloc_endx:section REL32END.endm/*;; =============;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER;; =============;;;; names of pseudo-sections for addLoader:;; LXUNFnnn Linux unfilter;; LXMRUnnn MostRecentlyUsed recoding of destinations;; MRUARBnn arbitrary number of entries in wheel;; MRUBITSn power of 2 entries in wheel (smaller code);; MRUBYTEn 256 entries in wheel (smallest code)*//*;; I got confused by the syntactic sugar of the fake %ifdefs.;; I can read the section name more easily when it is at the left margin.;; Also, some of the logic to select the sections is not that simple,;; and any mismatch between the logic and the %ifdefs is very confusing.;; Instead, I use comments after the section name, and blank lines for grouping.*/.macro ctojr32section LXUNF000 // enter at +0 for decompression; +2 for unfiltering jmps decompr0section LXUNF002 // 2+ address of decompress subroutine // unfilter(upx_byte *, length, cto8)lxunfilter: pop edx // return address pop eax // upx_byte *, same as addvalue pop ecx // length xchg eax, edi // edi= pointer; eax= saved_edi pusha // save C-convention ebx, ebp, esi, edi; also eax, edx// at most one of the next 2section MRUBYTE0 // 256==n_mru xor ebx, ebx // zerosection LXMRU005 // 0!=n_mru mov ebx, offset NMRU // modified N_MRU or N_MRU -1section LXMRU006 // 0!=n_mru push 0x0f // prefix of 6-byte Jcc <d32> pop eax mov ah, [esp + 8*4] // cto8section LXMRU007 // 0==n_mru push 0x0f // prefix of 6-byte Jcc <d32> pop ebx mov bh, [esp + 8*4] // cto8section LXUNF008 mov dl, [esp + 8*4] // cto8section LXUNF010 jmp lxunf0decompr0:// These #define are only if 0!=n_mru;// else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .#define __n_mru [esi]#define __n_mru1 [esi]#define __tail [esi + 4*1]#define __cto8_e8e9 [esi + 4*2]#define __cto8_0f [esi + 4*3]#define __addvalue [esi + 4*4]#define __tmp ebp#define __hand ebx#define __hand_l bl#define __kh edx#define __kh_l dlsection LXJCC010lxunf2: // have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32> movzxw ebp, [edi] // 2 bytes, zero-extendedsection LXMRU045 // 0!=n_mru sub ebp, __cto8_0fsection LXMRU046 // 0==n_mru sub ebp, ebxsection LXJCC020 // 0==n_mru, or Jcc excluded ('sub' of equals clears Carry) jnes unfcountsection LXJCC021 // 0!=n_mru and Jcc participates// must set Carry sub ebp, 1 // set Carry iff in range jnbs unfcountsection LXJCC023 // found Jcc// re-swap 0x8Y opcode and 0x0f prefix mov [edi -1], bl // 0x0f prefix dec ecx // preserve Carry mov [edi], al // Jcc opcode inc edi // preserve Carrysection LXUNF037#define __jc eaxlxunf: // in: Carry set iff we should apply mru and 0!=n_mru mov eax, [edi] // BE32 displacement with cto8 in low 8 bitssection LXUNF386 // 0!=n_mru && 386 pushfsection LXUNF387 // ==386 shr ax, 8 rol eax, 16 xchg ah, alsection LXUNF388 // 0!=n_mru && 386 popf jncs unf_store // do not apply mrusection LXUNF486 // >=486 mov al, 0 CPU 486 bswap eax // preserve Carry (2-byte instruction) CPU 386section LXUNF487 // 0!=n_mru && >=486 jncs unf_store // do not apply mrusection LXMRU065 // 0!=n_mru CPU 486 // (use faster but longer shr opcode sequence) shr __jc, 1 // eax= jc, or mru index CPU 386 jncs mru4 // not 1st time for this jcsection MRUBYTE3 dec __hand_lsection MRUARB30 dec __handsection MRUBITS3 and __hand, __n_mru1section MRUARB40 jge mru3 add __hand, __n_mrumru3:section LXMRU070 mov [esp + 4*__hand], __jc // 1st time: mru[hand] = jc jmps unf_storemru4: // not 1st time for this jc lea __kh, [__jc + __hand] // kh = jc + handsection MRUBYTE4 movzx __kh, __kh_lsection MRUBITS4 and __kh, __n_mru1section MRUARB50 cmp __kh, __n_mru jb mru5 sub __kh, __n_mrumru5:section LXMRU080 mov __jc, [esp + 4*__kh] // jc = mru[kh]section MRUBYTE5 dec __hand_lsection MRUARB60 dec __handsection MRUBITS5 and __hand, __n_mru1section MRUARB70 jge mru6 add __hand, __n_mrumru6:section LXMRU090 mov __tmp, [esp + 4*__hand] // tmp = mru[hand] test __tmp,__tmp jnzs mru8 push __jc // ran out of registers mov eax, __tailsection MRUBYTE6 dec alsection MRUARB80 dec eaxsection MRUBITS6 and eax, __n_mru1section MRUARB90 jge mru7 add eax, __n_mrumru7:section LXMRU100 xor __tmp,__tmp mov __tail, eax xchg [4+ esp + 4*eax], __tmp // tmp = mru[tail]; mru[tail] = 0 pop __jcmru8: mov [esp + 4*__kh ], __tmp // mru[kh] = tmp mov [esp + 4*__hand], __jc // mru[hand] = jcsection LXUNF040unf_store: sub eax, edi sub ecx, 4// one of the next2section LXMRU110 // 0!=n_mru add eax, __addvaluesection LXMRU111 // 0==n_mru add eax, esi // addvalue (same as initial pointer)section LXUNF041 mov [edi], eax add edi, 4 jmps unfcountsection LXUNF042lxunf0: // continuation of entry prolog for unfiltersection LEXEC016 // bug in APP: jmp and label must be in same .asx/.asy jmp lxunf0 // this instr does not really go here!section LXMRU010 // 0!=n_mru push eax // cto8_0fsection LXJMPA00 // only JMP, and not CALL, is filtered mov al, 0xE9section LXCALLB0 // only CALL, or both CALL and JMP are filtered mov al, 0xE8section LXUNF021 // common tail push eax // cto8_e8e9 push 0 // tail push ebx // n_mru or n_mru1 mov esi, esp // flat model "[esi]" saves a byte over "[ebp]"section LXMRU022 // 0==n_mru pop esi // addvalue mov edx, ebx // dh= cto8section LXJMPA01 // only JMP, and not CALL, is filtered mov dl, 0xE9section LXCALLB1 // only CALL, or both CALL and JMP are filtered mov dl, 0xE8section MRUBITS1 inc __hand // n_mru1 ==> n_mrusection LXMRU030lxunf1: // allocate and clear mru[] push 0// one of the next 2, if n_mrusection MRUBYTE1 dec __hand_lsection MRUARB10 dec __handsection LXMRU040 // 0!=n_mru jnzs lxunf1 // leaves 0=='hand'section LXUNF030lxctloop: movzxw eax, [edi] // 2 bytes, zero extended add edi, 1section LXJCC000 cmp al, 0x80 // lo of Jcc <d32> jb lxct1 cmp al, 0x8f // hi of Jcc <d32> jbes lxunf2lxct1:section LXCJ0MRU // 0==n_mru sub eax, edxsection LXCJ1MRU // 0!=n_mru sub eax, __cto8_e8e9// both CALL and JMP are filteredsection LXCALJMP sub eax, 1+ (0xE9 - 0xE8) // set Carry iff in range (result: -2, -1)// only CALL, or only JMP, is filteredsection LXCALL00 // 0==n_mru jes lxunfsection LXCALL01 // 0!=n_rmu sub eax, 1 // set Carry iff in rangesection LXCJ2MRU // 0==n_mru, or apply mru to all that are filtered here jbs lxunf // only Carry (Borrow) matterssection LXCJ4MRU // 0!=n_mru, but apply mru only to subset of filtered here jnbs unfcount // was not filtered anyway: do not unfilter//we will unfilter, and 0!=n_mru, but should we apply mru?section LXCJ6MRU // apply mru to JMP only (0xFF==al) jps lxct3 // jump if even number of 1 bits in alsection LXCJ7MRU // apply mru to CALL only (0xFE==al) jnps lxct3 // jump if odd number of 1 bits in alsection LXCJ8MRU // do not apply mru to one or both clclxct3: jmps lxunfsection LXUNF034unfcount: sub ecx, 1 jgs lxctloopsection LXMRU055 mov edi, esp // clear mru[] portion of stacksection MRUBYTE2 mov ecx, 4+ 256 // unused, tail, cto8_e8e9, cto8_0fsection MRUBITS2 mov ecx, __n_mru1 add ecx, 1+ 4 // n_mru1, tail, cto8_e8e9, cto8_0fsection MRUARB20 mov ecx, __n_mru add ecx, 4 // n_mru, tail, cto8_e8e9, cto8_0fsection LXMRU057 xor eax, eax rep stosd mov esp, edisection LXMRU058 // 0==n_mru push esisection LXUNF035 popa xchg eax, edi push ecx push eax push edx ret.endm// vi:ts=8:et:nowrap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -