You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.8 KiB
126 lines
4.8 KiB
<div align="center">
|
|
<div>
|
|
<img src="https://githacks.org/uploads/-/system/project/avatar/374/icon-5.png"/>
|
|
</div>
|
|
|
|
<p>use: git clone --recursive https://githacks.org/vmp2/vmprofiler.git</p>
|
|
|
|
</div>
|
|
|
|
### VMProfiler - Library To Profile VMProtect 2 Virtual Machines
|
|
|
|
vmprofiler is a c++ library which is used to statically analyze VMProtect 2 polymorphic virtual machines. This project is inherited in vmprofiler-qt, vmprofiler-cli, and vmemu. This is the base project for all other VMProtect 2 projects inside of this group on githacks.
|
|
|
|
# [Doxygen Documentation](https://docs.back.engineering/vmprofiler/index.html)
|
|
|
|
### Credit & Contributors
|
|
|
|
* [VTIL](https://github.com/vtil-project/VTIL-Core) - Virtual-machine Translation Intermediate Language
|
|
* [Zydis](https://github.com/zyantific/zydis) - Fast and lightweight x86/x86-64 disassembler library
|
|
* [irql0](https://github.com/irql0) - helped with the first version of vm handler pattern matching
|
|
|
|
### Basic Usage - Creating a vm::ctx_t Object
|
|
|
|
The `vm::ctx_t` class is a small container-like class which is simply used to contain all information for a given vm entry. This class contains the following useful information:
|
|
|
|
* all vm handlers for a given vm entry
|
|
* the linear virtual address of the module base in memory
|
|
* the image base address
|
|
* the image size in virtual memory
|
|
* which way VIP advances (exec_type)
|
|
* vm entry relative virtual address
|
|
* vm entry deobfuscated and flattened
|
|
* calc jmp deobfuscated and flattened
|
|
|
|
All of the above information is generated by executing the `vm::ctx_t::init` member function. Below is a C++ example of how to create a `vm::ctx_t` object.
|
|
|
|
```cpp
|
|
const auto module_base = reinterpret_cast< std::uintptr_t >(
|
|
LoadLibraryExA( parser.get< std::string >( "bin" ).c_str(),
|
|
NULL, DONT_RESOLVE_DLL_REFERENCES ) );
|
|
|
|
const auto vm_entry_rva = std::strtoull( parser.get< std::string >( "vmentry" ).c_str(), nullptr, 16 );
|
|
const auto image_base = umtils->image_base( parser.get< std::string >( "bin" ).c_str() );
|
|
const auto image_size = NT_HEADER( module_base )->OptionalHeader.SizeOfImage;
|
|
vm::ctx_t vmctx( module_base, image_base, image_size, vm_entry_rva );
|
|
|
|
if ( !vmctx.init() )
|
|
{
|
|
std::printf( "[!] failed to init vm::ctx_t... make sure all cli arguments are correct!\n" );
|
|
return -1;
|
|
}
|
|
```
|
|
|
|
### Using vm::ctx_t Object
|
|
|
|
Once you have instantiated `vm::ctx_t` and called `vm::ctx_t::init` with success, you now can directly access the data members of `vm::ctx_t`. Most importantly, `vm::ctx_t::calc_jmp`, `vm::ctx_t::vm_entry`, and `vm::ctx_t::vm_handlers`. An example usage of this data could be dumping the native x86_64 instructions which make up `vm::ctx_t::vm_entry`. Example c++ code for this is displayed below.
|
|
|
|
```cpp
|
|
std::puts( "======================== [vm entry] ========================\n" );
|
|
vm::util::print( vmctx.vm_entry );
|
|
```
|
|
|
|
***Output***
|
|
|
|
```
|
|
======================== [vm entry] ========================
|
|
> 0x00007FF7911A822C push 0xFFFFFFFF890001FA
|
|
> 0x00007FF7911A7FC9 push 0x45D3BF1F
|
|
> 0x00007FF7911A48E4 push r13
|
|
> 0x00007FF7911A4690 push rsi
|
|
> 0x00007FF7911A4E53 push r14
|
|
> 0x00007FF7911A74FB push rcx
|
|
> 0x00007FF7911A607C push rsp
|
|
> 0x00007FF7911A4926 pushfq
|
|
> 0x00007FF7911A4DC2 push rbp
|
|
> 0x00007FF7911A5C8C push r12
|
|
> 0x00007FF7911A52AC push r10
|
|
> 0x00007FF7911A51A5 push r9
|
|
> 0x00007FF7911A5189 push rdx
|
|
> 0x00007FF7911A7D5F push r8
|
|
> 0x00007FF7911A4505 push rdi
|
|
> 0x00007FF7911A4745 push r11
|
|
> 0x00007FF7911A478B push rax
|
|
> 0x00007FF7911A7A53 push rbx
|
|
> 0x00007FF7911A500D push r15
|
|
> 0x00007FF7911A6030 push [0x00007FF7911A7912]
|
|
> 0x00007FF7911A593A mov rax, 0x7FF6511A0000
|
|
> 0x00007FF7911A5955 mov r13, rax
|
|
> 0x00007FF7911A595F test dl, al
|
|
> 0x00007FF7911A5965 push rax
|
|
> 0x00007FF7911A5969 btr si, bx
|
|
> 0x00007FF7911A596F mov esi, [rsp+0xA0]
|
|
> 0x00007FF7911A5979 not esi
|
|
> 0x00007FF7911A5985 neg esi
|
|
> 0x00007FF7911A598D ror esi, 0x1A
|
|
> 0x00007FF7911A599E mov rbp, rsp
|
|
> 0x00007FF7911A59A8 sub rsp, 0x140
|
|
> 0x00007FF7911A59B5 and rsp, 0xFFFFFFFFFFFFFFF0
|
|
> 0x00007FF7911A59BE inc ax
|
|
> 0x00007FF7911A59C1 mov rdi, rsp
|
|
> 0x00007FF7911A59C7 bsr r12, rax
|
|
> 0x00007FF7911A59CB lea r12, [0x00007FF7911A6473]
|
|
> 0x00007FF7911A59DF mov rax, 0x100000000
|
|
> 0x00007FF7911A59EC add rsi, rax
|
|
> 0x00007FF7911A59F3 mov rbx, rsi
|
|
> 0x00007FF7911A59FA add rsi, [rbp]
|
|
> 0x00007FF7911A5A03 rcr dl, cl
|
|
> 0x00007FF7911A5A05 mov al, [rsi]
|
|
> 0x00007FF7911A5A0A xor al, bl
|
|
> 0x00007FF7911A5A11 neg al
|
|
> 0x00007FF7911A5A19 rol al, 0x05
|
|
> 0x00007FF7911A5A26 inc al
|
|
> 0x00007FF7911A5A2F xor bl, al
|
|
> 0x00007FF7911A5A34 movzx rax, al
|
|
> 0x00007FF7911A5A41 mov rdx, [r12+rax*8]
|
|
> 0x00007FF7911A5A49 xor rdx, 0x7F3D2149
|
|
> 0x00007FF7911A5507 inc rsi
|
|
> 0x00007FF7911A7951 add rdx, r13
|
|
> 0x00007FF7911A7954 jmp rdx
|
|
```
|
|
|
|
### License & Copyright
|
|
|
|
Copyright (c) 2021 _xeroxz, Independent Researcher @back.engineering
|
|
|
|
Licensed under the MIT License |