首页
论坛
课程
招聘
[原创]学习UPX对pe文件(x64)的加壳过程
2021-1-31 11:50 4573

[原创]学习UPX对pe文件(x64)的加壳过程

2021-1-31 11:50
4573


  • 压缩前

    1,将原pe文件按内存展开方式读入ibuf缓冲区,在区块数据后面拼接处理过的原导入表数数组oimport、重定位表orelocs等数据;

    2,清空区块数据中的调试目录Debug Directory、清空拷贝到oresources中的不压缩资源数据、重定位地址VA转换成相对rvamin的偏移并清空原重定位表;应该是为了提升压缩率

    3,自定义的导入表结构:

typedef struct _oimport{//要恢复的导入表数组oimport
    DWORD rva_dllname;	// +00 dll名称在新资源表oresources中的rva 0表示结束
    DWORD rva_iat;		// +04 iat的rva
    //之后是函数数组
    BYTE type;			// +08 类型 1表示之后是dll函数名称 0xff之后函数序号 	0xfe之后kernel32的函数名称rva 0表示当前dll不再有函数导入
    //根据不同的type之后可能是字符串、2字节的函数序号、4字节的rva
    
    //下一个dll
}

        4,自定义的重定位表,没有采用相对于每个块VirtualAddress的位移,而是使用相对前一个要处理的重定位地址的偏移


  • upx压缩

        1,Dos头、文件头原样输出,在头部最后添加了upx版本信息;

p->doPack(fo);
void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh,
                   unsigned subsystem_mask, upx_uint64_t default_imagebase,
                   bool last_section_rsrc_only)
                   readSectionHeaders(objs, sizeof(ih)); //读取节表 节表紧接在NtHeader之后
                   handleStub(fi,fo,pe_offset); //DosHeader、 DosStub等 NtHeader.OptionalHeader 之前的数据不做处理 直接输出
                   unsigned overlaystart = readSections(objs, ih.imagesize, ih.filealign, ih.datasize); //读入所有区块数据到ibuf

        2,将ibuf中从rvamin开始的数据压缩到obuf,保存到upx1开始的位置;

        3,紧接着的是壳代码loader,并作为新的oep;

        4,生成新线程局部存储otls;

void PeFile::processTls1(Interval *iv,
                         typename tls_traits<LEXX>::cb_value_t imagebase,
                         unsigned imagesize)
    //判断有多少个回调函数
    //保存重定位表中涉及tls的数据(在datastart与dataend之间)到临时结构tlsiv
    //如果原tls有回调函数,这里需要在otls最后预留2个位置用于存储回调函数tls_handler_offset和表示结束0填充回调函数
    //原tls目录整体保存到otls
    //将原TLS数据模板(datastart与dataend之间)的内容复制到ols
    //将原tls的AddressOfIndex字段设置为0
void PeFile::processTls2(Reloc *rel,const Interval *iv,unsigned newaddr,
                         typename tls_traits<LEXX>::cb_value_t imagebase) 
    //x32需要修正rel->add(tls_handler_offset + tls_handler_offset_reloc, reloc_type); x64不需要。应该是跟tls_handler的代码有关(待验证)
    //因为tls使用的是VA不是RVA,将otls的前几个数据都加入到新的重定位表
    //将tlsiv中涉及的需要修改的重定位数据添加到新的重定位表
    //修正原tls的数据模板(datastart、dataend)的VA地址
    //如果原tls有回调,将tls_handler_offset和0填充到otls最后的位置,将otls的callbacks修正为指向otls中tls_handler_offset正确的VA
    //因为tls使用的是VA不是RVA,将修正后的VA都要加入的新的重定位表

        5,生成新资源表oresources(程序默认图标等资源不能压缩);

void PeFile::processResources(Resource *res)//处理资源
    res->init(ibuf.subref("bad res %#x", vaddr, 1));
    start = res;
    root = head = current = NULL;//root指向根节点 head用于串联叶子节点 current用于遍历叶子节点
    dsize = ssize = 0;//dsize记录所有1-4级节点数据长度 ssize记录涉及到的unicode strings字符串占用长度
    root = convert(start,NULL,0);//从数组的最后1个元素向前遍历,所以head指向第一个叶子节点
    for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size()); //遍历所有叶子节点取资源[size+4(保存资源数据的原始RAV)]+dsize+ssize 一起赋值给soresources(即soresources为所有资源数据总长度)
    if (opt->win32_pe.compress_icons == 2)
        //取出第一个有图标的图标组中所有图标的id 格式3/id,(如"3/1,3/2,3/3,3/4")
    //遍历所有叶子节点
        //刚刚取出的第一个有图标的图标组及其下id对应的图标不压缩 其他的图标组及图标都压缩
        //0x10	版本信息 RT_VERSION 不压缩
        //0x18	MANIFEST元数据文件 不压缩
        //将不压缩的资源数据拷贝到ores中,清空其在ibuf中的数据
    //设置soresources为 未压缩资源[size+4(保存资源数据的原始RAV)]+dsize+ssize
void PeFile::callProcessResources(Resource &res, unsigned &ic)
    void PeFile::processResources(Resource *res,unsigned newaddr)
        //遍历叶子节点 将newoffset加上新的根元素地址
        upx_byte *p = res->build();//构建新的资源目录项
            build(root,bpos,spos,0);//bpos存储节点数据的偏移 spos存储涉及到的unicode strings字符串的偏移
        //将新的资源目录项拷贝到oresources的开始位置
    //设置新资源目录表的RVA和size  soresources为size

        6,生成新导入表oimpdlls;

const unsigned dllstrings = processImports(); //处理导入表
//不理解"*UND*"、 "*ZSTART" 等section的作用? (size为0)
    unsigned PeFile::processImports0(ord_mask_t ord_mask)
    //获取导入表涉及多少个dll
    //对dll进行排序
    ilinker = new ImportLinker(sizeof(LEXX)); //*UND* *ZSTART Dzero Zzero
    //addStubImports(); //将kernel32的 LoadLibraryA GetProcAddress ExitProcess VirtualProtect 添加到导入表
    //每个dll取1个函数 添加到导入表到ilinker (kernel32使用ordinals引入的全部添加)
    soimpdlls = ilinker->build();//soimpdlls新导入表长度 建立的output用来存储新的导入表数据
        qsort(sections, nsections, sizeof (Section*), ImportLinker::compare);	//排序
        addLoader(sections[ic]->name);	//将section->input复制到output 设置section的offset字段 使用next串联section
        //Dgbgehggbhagjdddccogegmgm advapi32.dll size:20
        //Dgdgpgngdhegmdddccogegmgm comctl32.dll
        //...
        //Dhfhdgfhcdddccogegmgm user32.dll
        //Dhfhihegigfgngfcogegmgm uxtheme.dll
        //Dzero
        //EgbgehggbhagjdddccogegmgmIfcgfghedgmgphdgfelgfhj advapi32.dll RegCloseKey size:8
        //EgbgehggbhagjdddccogegmgmKfi advapi32.dll X	//X相当于填充0
        //EgdgpgngdhegmdddccogegmgmIejgngbghgfemgjhdhefpeehcgbhh comctl32.dll ImageList_Draw
        //EgdgpgngdhegmdddccogegmgmKfi comctl32.dll X
        //...
        //EhfhihegigfgngfcogegmgmIejhdebhahafegigfgngfge uxtheme.dll IsAppThemed
        //EhfhihegigfgngfcogegmgmKfi uxtheme.dll X
        //Fgbgehggbhagjdddccogegmgm advapi32.dll size:dll名称长度+1
        //Fgdgpgngdhegmdddccogegmgm comctl32.dll
        //...
        //Fhfhihegigfgngfcogegmgm uxtheme.dll
        //GgbgehggbhagjdddccogegmgmLfcgfghedgmgphdgfelgfhj advapi32.dll RegCloseKey size:2
        //GgbgehggbhagjdddccogegmgmLfcgfghedgmgphdgfelgfhjX size:11
        //...
        //Zzero
void PeFile::processImports2(unsigned myimport, unsigned) 
    ilinker->relocate_import(myimport);
    oimpdlls = ilinker->getLoader(&len);//新的导入表 len返回新导入表长度 output赋值给oimpdlls
  • 执行壳代码loader

        1,将obuf中的数据解压到从upx0开始的位置;

        2,根据解压后oimport的数据使用kernel32中的LoadLibraryA和GetProcAddress初始化原iat;

        3,根据orelocs修正重定位数据;

        4,去除upx0、upx1区段的可写属性;

        5,跳转到真实oep继续执行

UPX1:000000013FE23B20                 public start
UPX1:000000013FE23B20 start           proc near
UPX1:000000013FE23B20                 push    rbx
UPX1:000000013FE23B21                 push    rsi
UPX1:000000013FE23B22                 push    rdi
UPX1:000000013FE23B23                 push    rbp
UPX1:000000013FE23B24                 lea     rsi, upx1_obuf  ; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B2B                 lea     rdi, [rsi-0AAC000h] ; rdi指向upx0的VA
UPX1:000000013FE23B32                 push    rdi
UPX1:000000013FE23B33                 xor     ebx, ebx
UPX1:000000013FE23B35                 xor     ecx, ecx
UPX1:000000013FE23B37                 or      rbp, 0FFFFFFFFFFFFFFFFh
UPX1:000000013FE23B3B                 call    loader_stub     ; 栈参数rdi指向upx0的VA
UPX1:000000013FE23B3B start           endp ; sp-analysis failed ; 寄存器
UPX1:000000013FE23B3B                                         ; ebx=0
UPX1:000000013FE23B3B                                         ; ecx=0
UPX1:000000013FE23B3B                                         ; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B3B                                         ; cld让方向标志位DF=0,std让DF=1
UPX1:000000013FE23B40
UPX1:000000013FE23B40 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B40
UPX1:000000013FE23B40 ; ebx左移1位如果为0
UPX1:000000013FE23B40 ;  取esi处的Dword给ebx
UPX1:000000013FE23B40 ;  rsi减-4
UPX1:000000013FE23B40 ;  ebx带进位左移1位
UPX1:000000013FE23B40 ;  从rsi处取1个字节给dl
UPX1:000000013FE23B40
UPX1:000000013FE23B40 get_ebx2_if0_rsi4ebx_rsi5dl proc near
UPX1:000000013FE23B40                 add     ebx, ebx
UPX1:000000013FE23B42                 jz      short loc_13FE23B46
UPX1:000000013FE23B44                 rep retn
UPX1:000000013FE23B46 ; ---------------------------------------------------------------------------
UPX1:000000013FE23B46
UPX1:000000013FE23B46 loc_13FE23B46:                          ; CODE XREF: get_ebx2_if0_rsi4ebx_rsi5dl+2↑j
UPX1:000000013FE23B46                 mov     ebx, [rsi]
UPX1:000000013FE23B48                 sub     rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23B4C                 adc     ebx, ebx
UPX1:000000013FE23B4E                 mov     dl, [rsi]
UPX1:000000013FE23B50                 rep retn
UPX1:000000013FE23B50 get_ebx2_if0_rsi4ebx_rsi5dl endp
UPX1:000000013FE23B50
UPX1:000000013FE23B52
UPX1:000000013FE23B52 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B52
UPX1:000000013FE23B52 ; 从rdi+rbp处开始复制ecx个字节到rdi处
UPX1:000000013FE23B52
UPX1:000000013FE23B52 copy2_rdi_from_rdirbp_ecx proc near     ; CODE XREF: loader_stub+A3↓p
UPX1:000000013FE23B52                 lea     rax, [rdi+rbp]
UPX1:000000013FE23B56                 cmp     ecx, 5
UPX1:000000013FE23B59                 mov     dl, [rax]
UPX1:000000013FE23B5B                 jbe     short loc_13FE23B7E
UPX1:000000013FE23B5D                 cmp     rbp, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23B61                 ja      short loc_13FE23B7E
UPX1:000000013FE23B63                 sub     ecx, 4
UPX1:000000013FE23B66
UPX1:000000013FE23B66 loc_13FE23B66:                          ; CODE XREF: copy2_rdi_from_rdirbp_ecx+23↓j
UPX1:000000013FE23B66                 mov     edx, [rax]
UPX1:000000013FE23B68                 add     rax, 4
UPX1:000000013FE23B6C                 sub     ecx, 4
UPX1:000000013FE23B6F                 mov     [rdi], edx
UPX1:000000013FE23B71                 lea     rdi, [rdi+4]
UPX1:000000013FE23B75                 jnb     short loc_13FE23B66
UPX1:000000013FE23B77                 add     ecx, 4
UPX1:000000013FE23B7A                 mov     dl, [rax]
UPX1:000000013FE23B7C                 jz      short locret_13FE23B8E
UPX1:000000013FE23B7E
UPX1:000000013FE23B7E loc_13FE23B7E:                          ; CODE XREF: copy2_rdi_from_rdirbp_ecx+9↑j
UPX1:000000013FE23B7E                                         ; copy2_rdi_from_rdirbp_ecx+F↑j ...
UPX1:000000013FE23B7E                 inc     rax
UPX1:000000013FE23B81                 mov     [rdi], dl
UPX1:000000013FE23B83                 sub     ecx, 1
UPX1:000000013FE23B86                 mov     dl, [rax]
UPX1:000000013FE23B88                 lea     rdi, [rdi+1]
UPX1:000000013FE23B8C                 jnz     short loc_13FE23B7E
UPX1:000000013FE23B8E
UPX1:000000013FE23B8E locret_13FE23B8E:                       ; CODE XREF: copy2_rdi_from_rdirbp_ecx+2A↑j
UPX1:000000013FE23B8E                 rep retn
UPX1:000000013FE23B8E copy2_rdi_from_rdirbp_ecx endp
UPX1:000000013FE23B8E
UPX1:000000013FE23B90
UPX1:000000013FE23B90 ; =============== S U B R O U T I N E =======================================
UPX1:000000013FE23B90
UPX1:000000013FE23B90 ; 栈参数rdi指向upx0的VA
UPX1:000000013FE23B90 ; 寄存器
UPX1:000000013FE23B90 ; ebx=0
UPX1:000000013FE23B90 ; ecx=0
UPX1:000000013FE23B90 ; rsi指向upx1的VA 即压缩后的数据obuf
UPX1:000000013FE23B90
UPX1:000000013FE23B90 loader_stub     proc near               ; CODE XREF: start+1B↑p
UPX1:000000013FE23B90
UPX1:000000013FE23B90 var_50          = byte ptr -50h
UPX1:000000013FE23B90 arg_0           = byte ptr  8
UPX1:000000013FE23B90
UPX1:000000013FE23B90 get_ebx2_if0_rsi4ebx_rsi5dl = r11
UPX1:000000013FE23B90                 cld
UPX1:000000013FE23B91                 pop     get_ebx2_if0_rsi4ebx_rsi5dl ; 返回地址 0x140053B40
UPX1:000000013FE23B93                 jmp     short loc_13FE23B9D
UPX1:000000013FE23B95 ; ---------------------------------------------------------------------------
UPX1:000000013FE23B95
UPX1:000000013FE23B95 loc_13FE23B95:                          ; CODE XREF: loader_stub:loc_13FE23BAD↓j
UPX1:000000013FE23B95                 inc     rsi
UPX1:000000013FE23B98                 mov     [rdi], dl       ; 复制dl中的1字节数据到rdi指向的upx0
UPX1:000000013FE23B9A                 inc     rdi             ; rsi、rdi指向下一个待处理数据
UPX1:000000013FE23B9D
UPX1:000000013FE23B9D loc_13FE23B9D:                          ; CODE XREF: loader_stub+3↑j
UPX1:000000013FE23B9D                                         ; loader_stub+A8↓j
UPX1:000000013FE23B9D                 mov     dl, [rsi]
UPX1:000000013FE23B9F                 add     ebx, ebx        ; 如果ebx不是0,从rsi处取1字节到dl,ebx左移1位
UPX1:000000013FE23BA1                 jnz     short loc_13FE23BAD ; ebx不是0跳转
UPX1:000000013FE23BA3                 mov     ebx, [rsi]      ; 如果ebx是0,重新从rsi处取Dword到ebx
UPX1:000000013FE23BA5                 sub     rsi, 0FFFFFFFFFFFFFFFCh ; rsi减-4
UPX1:000000013FE23BA9                 adc     ebx, ebx        ; ebx带进位左移1位
UPX1:000000013FE23BAB                 mov     dl, [rsi]       ; 从rsi处取1字节到dl
UPX1:000000013FE23BAD
UPX1:000000013FE23BAD loc_13FE23BAD:                          ; CODE XREF: loader_stub+11↑j
UPX1:000000013FE23BAD                 jb      short loc_13FE23B95 ; 判断CF进位标志位,为1时跳转
UPX1:000000013FE23BAF                 lea     eax, [rcx+1]
UPX1:000000013FE23BB2                 jmp     short loc_13FE23BBB
UPX1:000000013FE23BB4 ; ---------------------------------------------------------------------------
UPX1:000000013FE23BB4
UPX1:000000013FE23BB4 loc_13FE23BB4:                          ; CODE XREF: loader_stub:loc_13FE23BCE↓j
UPX1:000000013FE23BB4                 dec     eax
UPX1:000000013FE23BB6                 call    get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23BB9                 adc     eax, eax
UPX1:000000013FE23BBB
UPX1:000000013FE23BBB loc_13FE23BBB:                          ; CODE XREF: loader_stub+22↑j
UPX1:000000013FE23BBB                 call    get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23BBE                 adc     eax, eax
UPX1:000000013FE23BC0                 add     ebx, ebx
UPX1:000000013FE23BC2                 jnz     short loc_13FE23BCE
UPX1:000000013FE23BC4                 mov     ebx, [rsi]
UPX1:000000013FE23BC6                 sub     rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23BCA                 adc     ebx, ebx
UPX1:000000013FE23BCC                 mov     dl, [rsi]
UPX1:000000013FE23BCE
UPX1:000000013FE23BCE loc_13FE23BCE:                          ; CODE XREF: loader_stub+32↑j
UPX1:000000013FE23BCE                 jnb     short loc_13FE23BB4
UPX1:000000013FE23BD0                 sub     eax, 3
UPX1:000000013FE23BD3                 jb      short loc_13FE23BEE
UPX1:000000013FE23BD5                 shl     eax, 8
UPX1:000000013FE23BD8                 movzx   edx, dl
UPX1:000000013FE23BDB                 or      eax, edx
UPX1:000000013FE23BDD                 inc     rsi
UPX1:000000013FE23BE0                 xor     eax, 0FFFFFFFFh
UPX1:000000013FE23BE3                 jz      short loc_13FE23C3D ; 区块数据解压完成,准备开始处理导入表、重定位表等
UPX1:000000013FE23BE5                 sar     eax, 1
UPX1:000000013FE23BE7                 movsxd  rbp, eax
UPX1:000000013FE23BEA                 jb      short loc_13FE23C24
UPX1:000000013FE23BEC                 jmp     short loc_13FE23BFC
UPX1:000000013FE23BEE ; ---------------------------------------------------------------------------
UPX1:000000013FE23BEE
UPX1:000000013FE23BEE loc_13FE23BEE:                          ; CODE XREF: loader_stub+43↑j
UPX1:000000013FE23BEE                 add     ebx, ebx
UPX1:000000013FE23BF0                 jnz     short loc_13FE23BFA
UPX1:000000013FE23BF2                 mov     ebx, [rsi]
UPX1:000000013FE23BF4                 sub     rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23BF8                 adc     ebx, ebx
UPX1:000000013FE23BFA
UPX1:000000013FE23BFA loc_13FE23BFA:                          ; CODE XREF: loader_stub+60↑j
UPX1:000000013FE23BFA                 jb      short loc_13FE23C24
UPX1:000000013FE23BFC
UPX1:000000013FE23BFC loc_13FE23BFC:                          ; CODE XREF: loader_stub+5C↑j
UPX1:000000013FE23BFC                 inc     ecx
UPX1:000000013FE23BFE                 add     ebx, ebx
UPX1:000000013FE23C00                 jnz     short loc_13FE23C0A
UPX1:000000013FE23C02                 mov     ebx, [rsi]
UPX1:000000013FE23C04                 sub     rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23C08                 adc     ebx, ebx
UPX1:000000013FE23C0A
UPX1:000000013FE23C0A loc_13FE23C0A:                          ; CODE XREF: loader_stub+70↑j
UPX1:000000013FE23C0A                 jb      short loc_13FE23C24
UPX1:000000013FE23C0C
UPX1:000000013FE23C0C loc_13FE23C0C:                          ; CODE XREF: loader_stub:loc_13FE23C1D↓j
UPX1:000000013FE23C0C                 call    get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23C0F                 adc     ecx, ecx
UPX1:000000013FE23C11                 add     ebx, ebx
UPX1:000000013FE23C13                 jnz     short loc_13FE23C1D
UPX1:000000013FE23C15                 mov     ebx, [rsi]
UPX1:000000013FE23C17                 sub     rsi, 0FFFFFFFFFFFFFFFCh
UPX1:000000013FE23C1B                 adc     ebx, ebx
UPX1:000000013FE23C1D
UPX1:000000013FE23C1D loc_13FE23C1D:                          ; CODE XREF: loader_stub+83↑j
UPX1:000000013FE23C1D                 jnb     short loc_13FE23C0C
UPX1:000000013FE23C1F                 add     ecx, 2
UPX1:000000013FE23C22                 jmp     short loc_13FE23C29
UPX1:000000013FE23C24 ; ---------------------------------------------------------------------------
UPX1:000000013FE23C24
UPX1:000000013FE23C24 loc_13FE23C24:                          ; CODE XREF: loader_stub+5A↑j
UPX1:000000013FE23C24                                         ; loader_stub:loc_13FE23BFA↑j ...
UPX1:000000013FE23C24                 call    get_ebx2_if0_rsi4ebx_rsi5dl
UPX1:000000013FE23C27                 adc     ecx, ecx
UPX1:000000013FE23C29
UPX1:000000013FE23C29 loc_13FE23C29:                          ; CODE XREF: loader_stub+92↑j
UPX1:000000013FE23C29                 cmp     rbp, 0FFFFFFFFFFFFFB00h
UPX1:000000013FE23C30                 adc     ecx, 2
UPX1:000000013FE23C33                 call    copy2_rdi_from_rdirbp_ecx ; 从rdi+rbp处开始复制ecx个字节到rdi处
UPX1:000000013FE23C38                 jmp     loc_13FE23B9D
UPX1:000000013FE23C3D ; ---------------------------------------------------------------------------
UPX1:000000013FE23C3D
UPX1:000000013FE23C3D loc_13FE23C3D:                          ; CODE XREF: loader_stub+53↑j
UPX1:000000013FE23C3D                 pop     rsi
UPX1:000000013FE23C3E                 sub     rsp, 28h
UPX1:000000013FE23C42                 lea     rdi, [rsi+0C3C000h] ; rdi指向要恢复的导入表数组oimport
UPX1:000000013FE23C49
UPX1:000000013FE23C49 loc_13FE23C49:                          ; CODE XREF: loader_stub+E0↓j
UPX1:000000013FE23C49                 mov     eax, [rdi]      ; dll名称rva,0表示dll结束
UPX1:000000013FE23C4B                 or      eax, eax
UPX1:000000013FE23C4D                 jz      short loc_13FE23CA5 ; 完成原exe的iat的初始化
UPX1:000000013FE23C4F                 mov     ebx, [rdi+4]    ; iat的rva
UPX1:000000013FE23C52                 lea     rcx, [rax+rsi+0C5BBE4h] ; 获得dll名称
UPX1:000000013FE23C5A                 add     rbx, rsi        ; iat的va
UPX1:000000013FE23C5D                 add     rdi, 8
UPX1:000000013FE23C61                 call    large qword ptr cs:13FE2CD38h ; kernel32_LoadLibraryA
UPX1:000000013FE23C67                 xchg    rax, rbp        ; 将dll句柄保存到rbp
UPX1:000000013FE23C69
UPX1:000000013FE23C69 loc_13FE23C69:                          ; CODE XREF: loader_stub+10D↓j
UPX1:000000013FE23C69                 mov     al, [rdi]       ; 取之后函数的类型
UPX1:000000013FE23C69                                         ; 1表示之后是dll函数名称
UPX1:000000013FE23C69                                         ; 0xff之后函数序号
UPX1:000000013FE23C69                                         ; 0xfe之后kernel32的函数名称rva
UPX1:000000013FE23C6B                 inc     rdi
UPX1:000000013FE23C6E                 or      al, al
UPX1:000000013FE23C70                 jz      short loc_13FE23C49 ; 类型为0,表示函数结束
UPX1:000000013FE23C72                 jns     short loc_13FE23C7E
UPX1:000000013FE23C74                 movzx   rdx, word ptr [rdi] ; rdx=函数序号
UPX1:000000013FE23C78                 add     rdi, 2
UPX1:000000013FE23C7C                 jmp     short loc_13FE23C88 ; rcx=dll句柄
UPX1:000000013FE23C7E ; ---------------------------------------------------------------------------
UPX1:000000013FE23C7E
UPX1:000000013FE23C7E loc_13FE23C7E:                          ; CODE XREF: loader_stub+E2↑j
UPX1:000000013FE23C7E                 mov     rcx, rdi
UPX1:000000013FE23C81                 mov     rdx, rdi
UPX1:000000013FE23C84                 dec     eax
UPX1:000000013FE23C86                 repne scasb             ; rdx=函数名称
UPX1:000000013FE23C88
UPX1:000000013FE23C88 loc_13FE23C88:                          ; CODE XREF: loader_stub+EC↑j
UPX1:000000013FE23C88                 mov     rcx, rbp        ; rcx=dll句柄
UPX1:000000013FE23C8B                 call    large qword ptr cs:13FE2CD48h ; kernel32_GetProcAddress
UPX1:000000013FE23C91                 or      rax, rax        ; 函数地址
UPX1:000000013FE23C94                 jz      short loc_13FE23C9F ; 获取函数地址失败,则程序退出
UPX1:000000013FE23C96                 mov     [rbx], rax      ; 保存iat
UPX1:000000013FE23C99                 add     rbx, 8
UPX1:000000013FE23C9D                 jmp     short loc_13FE23C69 ; 取之后函数的类型
UPX1:000000013FE23C9D                                         ; 1表示之后是dll函数名称
UPX1:000000013FE23C9D                                         ; 0xff之后函数序号
UPX1:000000013FE23C9D                                         ; 0xfe之后kernel32的函数名称rva
UPX1:000000013FE23C9F ; ---------------------------------------------------------------------------
UPX1:000000013FE23C9F
UPX1:000000013FE23C9F loc_13FE23C9F:                          ; CODE XREF: loader_stub+104↑j
UPX1:000000013FE23C9F                 jmp     large qword ptr cs:13FE2CD40h ; ntdll_RtlExitUserProcess
UPX1:000000013FE23CA5 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CA5
UPX1:000000013FE23CA5 loc_13FE23CA5:                          ; CODE XREF: loader_stub+BD↑j
UPX1:000000013FE23CA5                 add     rsp, 28h
UPX1:000000013FE23CA9                 add     rdi, 4          ; rdi指向处理后的原重定位表orelocs
UPX1:000000013FE23CAD                 lea     rbx, [rsi-4]    ; rbx是重定位基址,指向upx0-4
UPX1:000000013FE23CB1
UPX1:000000013FE23CB1 loc_13FE23CB1:                          ; CODE XREF: loader_stub+13F↓j
UPX1:000000013FE23CB1                 xor     eax, eax
UPX1:000000013FE23CB3                 mov     al, [rdi]       ; 取1字节的oc
UPX1:000000013FE23CB5                 inc     rdi
UPX1:000000013FE23CB8                 or      eax, eax
UPX1:000000013FE23CBA                 jz      short loc_13FE23CE9 ; 0表示处理结束
UPX1:000000013FE23CBC                 cmp     al, 0EFh
UPX1:000000013FE23CBE                 ja      short loc_13FE23CD1 ; oc>=0xF0
UPX1:000000013FE23CC0
UPX1:000000013FE23CC0 loc_13FE23CC0:                          ; CODE XREF: loader_stub+14F↓j
UPX1:000000013FE23CC0                                         ; loader_stub+157↓j
UPX1:000000013FE23CC0                 add     rbx, rax        ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CC3                 mov     rax, [rbx]
UPX1:000000013FE23CC6                 bswap   rax
UPX1:000000013FE23CC9                 add     rax, rsi        ; rax转化成va
UPX1:000000013FE23CCC                 mov     [rbx], rax
UPX1:000000013FE23CCF                 jmp     short loc_13FE23CB1
UPX1:000000013FE23CD1 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CD1
UPX1:000000013FE23CD1 loc_13FE23CD1:                          ; CODE XREF: loader_stub+12E↑j
UPX1:000000013FE23CD1                 and     al, 0Fh         ; oc>=0xF0
UPX1:000000013FE23CD3                 shl     eax, 10h
UPX1:000000013FE23CD6                 mov     ax, [rdi]       ; 再取2字节
UPX1:000000013FE23CD9                 add     rdi, 2
UPX1:000000013FE23CDD                 or      eax, eax
UPX1:000000013FE23CDF                 jnz     short loc_13FE23CC0 ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CE1                 mov     eax, [rdi]      ; 刚取的2字节为0,说明后4字节为真实偏移
UPX1:000000013FE23CE3                 add     rdi, 4
UPX1:000000013FE23CE7                 jmp     short loc_13FE23CC0 ; rax是相对偏移,rbx为当前需要修复的重定位va
UPX1:000000013FE23CE9 ; ---------------------------------------------------------------------------
UPX1:000000013FE23CE9
UPX1:000000013FE23CE9 loc_13FE23CE9:                          ; CODE XREF: loader_stub+12A↑j
UPX1:000000013FE23CE9                 mov     rbp, large cs:13FE2CD50h ; kernel32_VirtualProtect
UPX1:000000013FE23CF0                 lea     rdi, [rsi-1000h]
UPX1:000000013FE23CF7                 mov     ebx, 1000h
UPX1:000000013FE23CFC                 push    rax
UPX1:000000013FE23CFD                 mov     r9, rsp         ; 保存原保护方式
UPX1:000000013FE23D00                 mov     r8d, 4          ; 保护方式 4 PAGE_READWRITE
UPX1:000000013FE23D06                 mov     rdx, rbx        ; 大小
UPX1:000000013FE23D09                 mov     rcx, rdi        ; 起始地址
UPX1:000000013FE23D0C                 sub     rsp, 20h
UPX1:000000013FE23D10                 call    rbp             ; kernel32_VirtualProtect
UPX1:000000013FE23D12                 lea     rax, [rdi+247h]
UPX1:000000013FE23D19                 and     byte ptr [rax], 7Fh ; 去除upx0区段的可写属性
UPX1:000000013FE23D1C                 and     byte ptr [rax+28h], 7Fh ; 去除upx1区段的可写属性
UPX1:000000013FE23D20                 lea     r9, [rsp+18h+arg_0]
UPX1:000000013FE23D25                 mov     r8, [r9]        ; 恢复原保护方式
UPX1:000000013FE23D28                 mov     rdx, rbx
UPX1:000000013FE23D2B                 mov     rcx, rdi
UPX1:000000013FE23D2E                 call    rbp             ; kernel32_VirtualProtect
UPX1:000000013FE23D30                 add     rsp, 28h
UPX1:000000013FE23D34                 pop     rbp
UPX1:000000013FE23D35                 pop     rdi
UPX1:000000013FE23D36                 pop     rsi
UPX1:000000013FE23D37                 pop     rbx
UPX1:000000013FE23D38                 lea     rax, [rsp-30h+var_50]
UPX1:000000013FE23D3D
UPX1:000000013FE23D3D loc_13FE23D3D:                          ; CODE XREF: loader_stub+1B2↓j
UPX1:000000013FE23D3D                 push    0               ; 平衡栈
UPX1:000000013FE23D3F                 cmp     rsp, rax
UPX1:000000013FE23D42                 jnz     short loc_13FE23D3D ; 平衡栈
UPX1:000000013FE23D44                 sub     rsp, 0FFFFFFFFFFFFFF80h
UPX1:000000013FE23D48                 jmp     oep_real         ; 壳代码执行完毕,跳转到原oep继续执行
UPX1:000000013FE23D48 loader_stub     endp ; sp-analysis failed


安卓应用层抓包通杀脚本发布!《高研班》2021年6月班开始招生!

最后于 2021-1-31 11:54 被kobsky编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (7)
雪    币: 1156
活跃值: 活跃值 (416)
能力值: (RANK:250 )
在线值:
发帖
回帖
粉丝
xiaohang 活跃值 3 2021-1-31 21:11
2
0
之前论坛内upx的内容多关注于脱壳的过程,但对upx加壳的过程少有提及,楼主的文章可以作为不错的补充,谢谢分享
雪    币: 60
活跃值: 活跃值 (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
CCDmichael 活跃值 2021-1-31 21:49
3
0
相当相当好,感谢分享
雪    币: 2497
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xghoecki 活跃值 2021-2-1 01:46
4
0
坛里有你更精 ,感谢分享
雪    币: 8832
活跃值: 活跃值 (3438)
能力值: ( LV12,RANK:252 )
在线值:
发帖
回帖
粉丝
一半人生 活跃值 4 2021-2-2 08:50
5
0
幸苦
雪    币: 4701
活跃值: 活跃值 (566)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
alphc 活跃值 2021-2-5 00:32
6
0
真的详细,先码住等有空了慢慢看
雪    币: 207
活跃值: 活跃值 (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
菜菜小J 活跃值 2021-2-13 00:59
7
0
感谢分享
雪    币: 14
活跃值: 活跃值 (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cspg 活跃值 2021-2-26 17:01
8
0
感谢分享
游客
登录 | 注册 方可回帖
返回