Repository: jeremybeaume/tools Branch: master Commit: fb48c2dbb3d7 Files: 19 Total size: 51.2 KB Directory structure: gitextract_6wf3dbfx/ ├── IDA_plugin/ │ └── param_enum.py ├── README.md ├── disable-defender.ps1 └── pin-unpacker/ ├── .gitignore ├── IAT.cpp ├── IAT.h ├── IAT_repair.py ├── MyPinTool.vcxproj ├── MyPinTool.vcxproj.user ├── README.md ├── Unpacker.sln ├── Upacker.cpp ├── export.h ├── export_pin.cpp ├── export_windows.cpp ├── pin_utils.cpp ├── pin_utils.h ├── utils.cpp └── utils.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: IDA_plugin/param_enum.py ================================================ """ Replace immediate values push before a call by enum value """ from idc import * from idaapi import * from idautils import * from ida_enum import * def replace_pushed_int(function_ea, target_push_n, target_enum_name, before_limit=0x30, int_type="hex"): """ Replace the last immediate value push before by enum value if possible function_ea : target function ea (will check Xref to this ea) for structs use get_name_ea_simple target_push_n : how many push back we want, starts at 1 target_enum_name : enum to target (created if doesn't exists) before_limit : how much back we agree to go str_type : "hex" or "dec", used for the enum value names (in hex or dec number) """ target_enum = get_enum(target_enum_name) if target_enum == BADADDR: if int_type == "hex": target_enum = add_enum(0, target_enum_name, hex_flag()) else: target_enum = add_enum(0, target_enum_name, dec_flag()) for xref in XrefsTo(function_ea, 0): current_ea = xref.frm push_n = 0 while current_ea != BADADDR: current_ea = prev_head(current_ea, xref.frm - before_limit) if print_insn_mnem(current_ea) == "push": push_n += 1 if push_n == target_push_n: # that's the push we are looking for type_n = get_operand_type(current_ea, 0) if type_n == 5: # immediate value value = get_operand_value(current_ea, 0) enum_value = get_enum_member(target_enum, value, 0, 0) if enum_value == BADADDR: # Create a new enum value if int_type == "hex": enum_val_name = "{:02X}".format(value) else: enum_val_name = str(value) enum_value = add_enum_member(target_enum, get_enum_name(target_enum) + "_" + enum_val_name, value) op_enum(current_ea, 0, target_enum, 0) else: # not an immediate value print(f"Help needed @ {hex(current_ea)}") break # Done here, break to the next Xref ================================================ FILE: README.md ================================================ Collection of tools developped by myself. Some of them may have articles describing them on my [blog](https://bidouillesecurity.com) ================================================ FILE: disable-defender.ps1 ================================================ # Disable Windows Defender <# _ _ __ ____ _ _ __ _ __ (_)_ __ __ _ | | \ \ /\ / / _` | '__| '_ \| | '_ \ / _` | | | \ V V / (_| | | | | | | | | | | (_| | |_| \_/\_/ \__,_|_| |_| |_|_|_| |_|\__, | (_) |___/ This script is NOT a disable/enable solution, I'm a malware analyst, I use it for malware analysis. It can completely DELETE Defender, and it is NOT REVERSIBLE (that's what I need). Once you have run it, you will no longer have any sort of antivirus protection, and WILL NOT BE ABLE to reactivate it. Think twice before running it, or read the blog post to understand and modify it to suit **your** needs. THIS IS NOT A JOKE. YOU HAVE BEEN WARNED. #> <# Options : -Delete : delete the defender related files (services, drivers, executables, ....) Source : https://bidouillesecurity.com/disable-windows-defender-in-powershell #> Write-Host "[+] Disable Windows Defender (as $(whoami))" ## STEP 0 : elevate if needed if(-Not $($(whoami) -eq "nt authority\system")) { $IsSystem = $false # Elevate to admin (needed when called after reboot) if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) { Write-Host " [i] Elevate to Administrator" $CommandLine = "-ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine Exit } # Elevate to SYSTEM if psexec is available $psexec_path = $(Get-Command PsExec -ErrorAction 'ignore').Source if($psexec_path) { Write-Host " [i] Elevate to SYSTEM" $CommandLine = " -i -s powershell.exe -ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments Start-Process -WindowStyle Hidden -FilePath $psexec_path -ArgumentList $CommandLine exit } else { Write-Host " [i] PsExec not found, will continue as Administrator" } } else { $IsSystem = $true } ## STEP 1 : Disable everything we can with immediate effect Write-Host " [+] Add exclusions" # Add the whole system in Defender exclusions 67..90|foreach-object{ $drive = [char]$_ Add-MpPreference -ExclusionPath "$($drive):\" -ErrorAction SilentlyContinue Add-MpPreference -ExclusionProcess "$($drive):\*" -ErrorAction SilentlyContinue } Write-Host " [+] Disable scanning engines (Set-MpPreference)" Set-MpPreference -DisableArchiveScanning 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableBehaviorMonitoring 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableIntrusionPreventionSystem 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableIOAVProtection 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableRemovableDriveScanning 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableBlockAtFirstSeen 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableScanningNetworkFiles 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableScriptScanning 1 -ErrorAction SilentlyContinue Set-MpPreference -DisableRealtimeMonitoring 1 -ErrorAction SilentlyContinue Write-Host " [+] Set default actions to Allow (Set-MpPreference)" Set-MpPreference -LowThreatDefaultAction Allow -ErrorAction SilentlyContinue Set-MpPreference -ModerateThreatDefaultAction Allow -ErrorAction SilentlyContinue Set-MpPreference -HighThreatDefaultAction Allow -ErrorAction SilentlyContinue ## STEP 2 : Disable services, we cannot stop them, but we can disable them (they won't start next reboot) Write-Host " [+] Disable services" $need_reboot = $false # WdNisSvc Network Inspection Service # WinDefend Antivirus Service # Sense : Advanced Protection Service $svc_list = @("WdNisSvc", "WinDefend", "Sense") foreach($svc in $svc_list) { if($(Test-Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc")) { if( $(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc").Start -eq 4) { Write-Host " [i] Service $svc already disabled" } else { Write-Host " [i] Disable service $svc (next reboot)" Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc" -Name Start -Value 4 $need_reboot = $true } } else { Write-Host " [i] Service $svc already deleted" } } Write-Host " [+] Disable drivers" # WdnisDrv : Network Inspection System Driver # wdfilter : Mini-Filter Driver # wdboot : Boot Driver $drv_list = @("WdnisDrv", "wdfilter", "wdboot") foreach($drv in $drv_list) { if($(Test-Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv")) { if( $(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv").Start -eq 4) { Write-Host " [i] Driver $drv already disabled" } else { Write-Host " [i] Disable driver $drv (next reboot)" Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv" -Name Start -Value 4 $need_reboot = $true } } else { Write-Host " [i] Driver $drv already deleted" } } # Check if service running or not if($(GET-Service -Name WinDefend).Status -eq "Running") { Write-Host " [+] WinDefend Service still running (reboot required)" $need_reboot = $true } else { Write-Host " [+] WinDefend Service not running" } ## STEP 3 : Reboot if needed, add a link to the script to Startup (will be runned again after reboot) $link_reboot = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\disable-defender.lnk" Remove-Item -Force "$link_reboot" -ErrorAction 'ignore' # Remove the link (only execute once after reboot) if($need_reboot) { Write-Host " [+] This script will be started again after reboot." -BackgroundColor DarkRed -ForegroundColor White $powershell_path = '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"' $cmdargs = "-ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments $res = New-Item $(Split-Path -Path $link_reboot -Parent) -ItemType Directory -Force $WshShell = New-Object -comObject WScript.Shell $shortcut = $WshShell.CreateShortcut($link_reboot) $shortcut.TargetPath = $powershell_path $shortcut.Arguments = $cmdargs $shortcut.WorkingDirectory = "$(Split-Path -Path $PSScriptRoot -Parent)" $shortcut.Save() } else { ## STEP 4 : After reboot (we checked that everything was successfully disabled), make sure it doesn't come up again ! if($IsSystem) { # Configure the Defender registry to disable it (and the TamperProtection) # editing HKLM:\SOFTWARE\Microsoft\Windows Defender\ requires to be SYSTEM Write-Host " [+] Disable all functionnalities with registry keys (SYSTEM privilege)" # Cloud-delivered protection: Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Real-Time Protection" -Name SpyNetReporting -Value 0 # Automatic Sample submission Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Real-Time Protection" -Name SubmitSamplesConsent -Value 0 # Tamper protection Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Features" -Name TamperProtection -Value 4 # Disable in registry Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender" -Name DisableAntiSpyware -Value 1 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" -Name DisableAntiSpyware -Value 1 } else { Write-Host " [W] (Optional) Cannot configure registry (not SYSTEM)" } if($MyInvocation.UnboundArguments -And $($MyInvocation.UnboundArguments.tolower().Contains("-delete"))) { # Delete Defender files function Delete-Show-Error { $path_exists = Test-Path $args[0] if($path_exists) { Remove-Item -Recurse -Force -Path $args[0] } else { Write-Host " [i] $($args[0]) already deleted" } } Write-Host "" Write-Host "[+] Delete Windows Defender (files, services, drivers)" # Delete files Delete-Show-Error "C:\ProgramData\Windows\Windows Defender\" Delete-Show-Error "C:\ProgramData\Windows\Windows Defender Advanced Threat Protection\" # Delete drivers Delete-Show-Error "C:\Windows\System32\drivers\wd\" # Delete service registry entries foreach($svc in $svc_list) { Delete-Show-Error "HKLM:\SYSTEM\CurrentControlSet\Services\$svc" } # Delete drivers registry entries foreach($drv in $drv_list) { Delete-Show-Error "HKLM:\SYSTEM\CurrentControlSet\Services\$drv" } } } Write-Host "" Read-Host -Prompt "Press any key to continue" ================================================ FILE: pin-unpacker/.gitignore ================================================ test/ x64/ x86/ IAT.json *.exe *.dll .vs/ ================================================ FILE: pin-unpacker/IAT.cpp ================================================ #include #include #include "IAT.h" #include "utils.h" using std::endl; void IAT_add_library(IAT_table& table, char* DLL_Name, ADDRINT LoadLibrary_addr) { struct IAT_DLL_entry& funct_entry = table[std::string(DLL_Name)]; if (funct_entry.LoadLibrary_addr != 0) { funct_entry.LoadLibrary_addr = LoadLibrary_addr; } } void IAT_add_function(IAT_table& table, char* DLL_Name, char* function_name, ADDRINT function_addr, ADDRINT GetProcAddress_addr) { struct IAT_Func_entry entry; entry.Function_name = std::string(function_name); entry.IAT_RVA = function_addr; entry.GetProcAddress_addr = GetProcAddress_addr; struct IAT_DLL_entry& funct_entry = table[std::string(DLL_Name)]; funct_entry.functions.push_back(entry); } void IAT_print(const IAT_table& table, std::ostream* out) { *out << "=== IAT ===" << endl; for (std::pair element : table) { *out << element.first << " (Loaded @ " << int_to_hex(element.second.LoadLibrary_addr) << ")" << endl; for (struct IAT_Func_entry entry : element.second.functions) { *out << " " << entry.Function_name << " @ " << int_to_hex(entry.IAT_RVA) << " (Loaded @ " << int_to_hex(entry.GetProcAddress_addr) << ")" << endl; } } } void IAT_json_save(const IAT_table& table, const std::string& path) { std::ofstream outFile; outFile.open(path.c_str()); outFile << "{\n \"DLL\":{\n"; bool first_DLL = true; for (std::pair element : table) { if (!first_DLL) { outFile << ",\n"; } first_DLL = false; outFile << " \"" << element.first << "\":{\n"; outFile << " \"LoadLibrary_RVA\":\"" << int_to_hex(element.second.LoadLibrary_addr) << "\",\n"; outFile << " \"functions\":{\n"; bool first_function = true; for (struct IAT_Func_entry entry : element.second.functions) { if (!first_function) { outFile << ",\n"; } first_function = false; outFile << " \"" << entry.Function_name << "\":{\n"; outFile << " \"IAT_RVA\":\"" << int_to_hex(entry.IAT_RVA) <<"\",\n"; outFile << " \"GetProcAddress_RVA\":\"" << int_to_hex(entry.GetProcAddress_addr) << "\"\n"; outFile << " }"; } outFile << "\n }\n"; outFile << " }"; } outFile << "\n }\n}\n"; outFile.close(); std::cerr << "IAT saved in " << path << endl; } ================================================ FILE: pin-unpacker/IAT.h ================================================ #pragma once #include #include #include "pin.H" struct IAT_Func_entry { std::string Function_name; ADDRINT IAT_RVA; ADDRINT GetProcAddress_addr; }; struct IAT_DLL_entry { ADDRINT LoadLibrary_addr; std::vector functions; }; typedef std::map IAT_table; void IAT_add_library(IAT_table& table, char* DLL_Name, ADDRINT LoadLibrary_addr); void IAT_add_function(IAT_table& table, char* DLL_Name, char* function_name, ADDRINT function_addr, ADDRINT GetProcAddress_addr); void IAT_print(const IAT_table& table, std::ostream* out); void IAT_json_save(const IAT_table& table, const std::string& path); ================================================ FILE: pin-unpacker/IAT_repair.py ================================================ import argparse import lief import os import json def align(x, al): """ return aligned to """ if x % al == 0: return x else: return x - (x % al) + al def pad_data(data, al): """ return padded with 0 to a size aligned with """ return data + ([0] * (align(len(data), al) - len(data))) class ImportTableBuilder: def __init__(self, baseoffset, ptr_size): self.data = b"" self.hint_name_RVA_dict = {} self.name_thunk_RVA_dict = {} self.baseoffset = baseoffset self.IDT_RVA = 0 self.ptr_size = ptr_size def _add_name(self, name, hint=0): self.hint_name_RVA_dict[name] = self.baseoffset + len(self.data) self.data += b"\x00\x00" # hint field, added even for DLL names self.data += name.encode("ASCII") + b'\x00' def _add_thunk_list(self, dllname, name_list): self.name_thunk_RVA_dict[dllname] = self.baseoffset + len(self.data) for n in name_list: self._push(self.hint_name_RVA_dict[n], self.ptr_size) self._push(0, self.ptr_size) #end of the array def _add_import_descriptor(self, dllname, IAT_RVA): if(self.IDT_RVA ==0): self.IDT_RVA = self.baseoffset + len(self.data) self._push(self.name_thunk_RVA_dict[dllname], 4) #OriginalFirstThunk self._push(0, 4) #TimeDateStamp self._push(0, 4) #ForwarderChain self._push(self.hint_name_RVA_dict[dllname] + 2, 4) #DLLname, + 2 to ignore hint field self._push(IAT_RVA, 4) #FirstThunk def _push(self, val, size): self.data += val.to_bytes(size, "little") def _init_IAT(self, input_PE, base_IAT_addr, name_list): """ Init the IAT to point to the functions names we created """ rva = base_IAT_addr for n in name_list: data = list(self.hint_name_RVA_dict[n].to_bytes(self.ptr_size, "little")) input_PE.patch_address(rva, data, lief.Binary.VA_TYPES.RVA) rva += self.ptr_size def build(self, imports_names, IAT_locations, input_PE): """ import_names = { 'DLL_name':['functions_names'] } IAT_locations = {'DLL_name':RVA} """ for dll_name, func_names_list in imports_names.items(): self._add_name(dll_name) for fun_name in func_names_list: self._add_name(fun_name) self._add_thunk_list(dll_name, func_names_list) self._init_IAT(input_PE, IAT_locations[dll_name], func_names_list) for dll_name in imports_names.keys(): self._add_import_descriptor(dll_name, IAT_locations[dll_name]) self._push(0, 20) # empty import_descriptor to finish the array if __name__ =="__main__" : parser = argparse.ArgumentParser(description='Pack PE binary') parser.add_argument('input', metavar="FILE", help='input PE file') parser.add_argument('iat_file', metavar="IAT FILE", help='input IAT json file') parser.add_argument('-o', metavar="FILE", help='output', default="IAT_corrected.exe") args = parser.parse_args() with open(args.iat_file, "r") as f: IAT_data = json.load(f) input_PE = lief.PE.parse(args.input) # get RVA for new section max_RVA = max([x.virtual_address + x.size for x in input_PE.sections]) max_RVA = align(max_RVA, input_PE.optional_header.section_alignment) import_names = {} IAT_locations = {} for dll_name in IAT_data["DLL"].keys(): import_names[dll_name] = [] IAT_locations[dll_name] = 0 func_dict = IAT_data["DLL"][dll_name]["functions"] for fun_name in func_dict.keys(): import_names[dll_name] += [fun_name] IAT_loc = min([int(infos["IAT_RVA"], 16) for (name, infos) in func_dict.items()]) IAT_locations[dll_name] = IAT_loc builder = ImportTableBuilder(max_RVA, 8) builder.build(import_names, IAT_locations, input_PE) import_data = pad_data(list(builder.data), input_PE.optional_header.file_alignment) import_section = lief.PE.Section(name=".imp") import_section.content = import_data import_section.size = len(import_data) import_section.virtual_address = max_RVA import_section.characteristics = (lief.PE.SECTION_CHARACTERISTICS.MEM_READ | lief.PE.SECTION_CHARACTERISTICS.MEM_WRITE) input_PE.add_section(import_section) # change the file ehaders # make lief compute the new sizeof_image input_PE.optional_header.sizeof_image = 0 # chagne the Import table to point to ours import_data_dir = input_PE.data_directory(lief.PE.DATA_DIRECTORY.IMPORT_TABLE) import_data_dir.rva = builder.IDT_RVA import_data_dir.size = len(builder.data) # not supposed to move (no reloctions table) input_PE.optional_header.dll_characteristics = 0 # make all sections writable (make sur the IAT is writable) for s in input_PE.sections: s.characteristics = s.characteristics | lief.PE.SECTION_CHARACTERISTICS.MEM_WRITE # save the resulting PE if(os.path.exists(args.o)): # little trick here : lief emits no warning when it cannot write because the output # file is already opened. Using this function ensure we fail in this case (avoid errors). os.remove(args.o) builder = lief.PE.Builder(input_PE) builder.build() builder.write(args.o) print(f"Output saved in {args.o}") ================================================ FILE: pin-unpacker/MyPinTool.vcxproj ================================================  Debug Win32 Debug x64 Release Win32 Release x64 {639EF517-FCFC-408E-9500-71F0DC0458DB} MyPinTool Win32Proj 10.0 Unpacker DynamicLibrary MultiByte true v142 DynamicLibrary MultiByte v142 x86 DynamicLibrary MultiByte true v142 DynamicLibrary MultiByte v142 <_ProjectFileVersion>10.0.40219.1 $(ProjectDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(ProjectDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(ProjectDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(ProjectDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) Disabled $(PINTOOLS_DIR)\source\include\pin;$(PINTOOLS_DIR)\source\include\pin\gen;$(PINTOOLS_DIR)\source\toolsInstLib;$(PINTOOLS_DIR)\extras\xed-ia32\include\xed;$(PINTOOLS_DIR)\extras\components\include;$(PINTOOLS_DIR)\extras\stlport\include;$(PINTOOLS_DIR)\extras;$(PINTOOLS_DIR)\extras\libstdc++\include;$(PINTOOLS_DIR)\extras\crt\include;$(PINTOOLS_DIR)\extras\crt;$(PINTOOLS_DIR)\extras\crt\include\arch-x86;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi\asm-x86;%(AdditionalIncludeDirectories);$(WindowsSdkDir)\include TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__;_WINDOWS_H_PATH_=$(WIN10SDK_INCLUDE)/um false Default MultiThreadedDebugDLL false true NotSet false Level3 ProgramDatabase 4530;5208;%(DisableSpecificWarnings) stdcpp17 stdc17 /export:main /ignore:4210 /ignore:4281 %(AdditionalOptions) pin.lib;xed.lib;pinvm.lib;pincrt.lib;ntdll-32.lib;kernel32.lib;crtbeginS.obj $(PINTOOLS_DIR)\ia32\lib;$(PINTOOLS_DIR)\ia32\lib-ext;$(PINTOOLS_DIR)\extras\xed-ia32\lib;$(PINTOOLS_DIR)\ia32\runtime\pincrt;%(AdditionalLibraryDirectories);$(WindowsSdkDir)\lib true %(IgnoreSpecificDefaultLibraries) true NotSet false Ptrace_DllMainCRTStartup%4012 0x55000000 MachineX86 true false X64 /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) Disabled $(PINTOOLS_DIR)\source\include\pin;$(PINTOOLS_DIR)\source\include\pin\gen;$(PINTOOLS_DIR)\source\toolsInstLib;$(PINTOOLS_DIR)\extras\xed-intel64\include\xed;$(PINTOOLS_DIR)\extras\components\include;$(PINTOOLS_DIR)\extras\stlport\include;$(PINTOOLS_DIR)\extras;$(PINTOOLS_DIR)\extras\libstdc++\include;$(PINTOOLS_DIR)\extras\crt\include;$(PINTOOLS_DIR)\extras\crt;$(PINTOOLS_DIR)\extras\crt\include\arch-x86_64;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi\asm-x86;$(WindowsSdkDir)\include;%(AdditionalIncludeDirectories);$(WindowsSdkDir)\include TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__;_WINDOWS_H_PATH_=$(WIN10SDK_INCLUDE)/um false Default MultiThreadedDebugDLL false true false Level3 ProgramDatabase 4530;5208;%(DisableSpecificWarnings) stdcpp17 stdc17 /export:main /ignore:4210 /ignore:4281 %(AdditionalOptions) pin.lib;xed.lib;pinvm.lib;pincrt.lib;ntdll-64.lib;kernel32.lib;crtbeginS.obj $(PINTOOLS_DIR)\intel64\lib;$(PINTOOLS_DIR)\intel64\lib-ext;$(PINTOOLS_DIR)\extras\xed-intel64\lib;$(PINTOOLS_DIR)\intel64\runtime\pincrt;$(WindowsSdkDir)\lib;%(AdditionalLibraryDirectories);$(WindowsSdkDir)\lib true %(IgnoreSpecificDefaultLibraries) true NotSet false Ptrace_DllMainCRTStartup 0xC5000000 MachineX64 true /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) false false $(PINTOOLS_DIR)\source\include\pin;$(PINTOOLS_DIR)\source\include\pin\gen;$(PINTOOLS_DIR)\source\toolsInstLib;$(PINTOOLS_DIR)\extras\xed-ia32\include\xed;$(PINTOOLS_DIR)\extras\components\include;$(PINTOOLS_DIR)\extras\stlport\include;$(PINTOOLS_DIR)\extras;$(PINTOOLS_DIR)\extras\libstdc++\include;$(PINTOOLS_DIR)\extras\crt\include;$(PINTOOLS_DIR)\extras\crt;$(PINTOOLS_DIR)\extras\crt\include\arch-x86;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi\asm-x86;%(AdditionalIncludeDirectories);$(WindowsSdkDir)\include TARGET_IA32;HOST_IA32;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__i386__;_WINDOWS_H_PATH_=$(WIN10SDK_INCLUDE)/um false Default MultiThreadedDLL false true NotSet false Level3 4530;5208;%(DisableSpecificWarnings) stdcpp17 stdc17 /export:main /ignore:4210 /ignore:4281 %(AdditionalOptions) pin.lib;xed.lib;pinvm.lib;pincrt.lib;ntdll-32.lib;kernel32.lib;crtbeginS.obj $(PINTOOLS_DIR)\ia32\lib;$(PINTOOLS_DIR)\ia32\lib-ext;$(PINTOOLS_DIR)\extras\xed-ia32\lib;$(PINTOOLS_DIR)\ia32\runtime\pincrt;%(AdditionalLibraryDirectories);$(WindowsSdkDir)\lib true %(IgnoreSpecificDefaultLibraries) true NotSet true Ptrace_DllMainCRTStartup%4012 0x55000000 MachineX86 false X64 /GR- /GS- /EHs- /EHa- /Oi- /FIinclude/msvc_compat.h %(AdditionalOptions) false false $(PINTOOLS_DIR)\source\include\pin;$(PINTOOLS_DIR)\source\include\pin\gen;$(PINTOOLS_DIR)\source\toolsInstLib;$(PINTOOLS_DIR)\extras\xed-intel64\include\xed;$(PINTOOLS_DIR)\extras\components\include;$(PINTOOLS_DIR)\extras\stlport\include;$(PINTOOLS_DIR)\extras;$(PINTOOLS_DIR)\extras\libstdc++\include;$(PINTOOLS_DIR)\extras\crt\include;$(PINTOOLS_DIR)\extras\crt;$(PINTOOLS_DIR)\extras\crt\include\arch-x86_64;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi;$(PINTOOLS_DIR)\extras\crt\include\kernel\uapi\asm-x86;$(WindowsSdkDir)\include;%(AdditionalIncludeDirectories);$(WindowsSdkDir)\include TARGET_IA32E;HOST_IA32E;TARGET_WINDOWS;__PIN__=1;PIN_CRT=1;__LP64__;_WINDOWS_H_PATH_=$(WIN10SDK_INCLUDE)/um false Default MultiThreadedDLL false true false Level3 4530;5208;%(DisableSpecificWarnings) stdcpp17 stdc17 /export:main /ignore:4210 /ignore:4281 %(AdditionalOptions) pin.lib;xed.lib;pinvm.lib;pincrt.lib;ntdll-64.lib;kernel32.lib;crtbeginS.obj $(PINTOOLS_DIR)\intel64\lib;$(PINTOOLS_DIR)\intel64\lib-ext;$(PINTOOLS_DIR)\extras\xed-intel64\lib;$(PINTOOLS_DIR)\intel64\runtime\pincrt;$(WindowsSdkDir)\lib;%(AdditionalLibraryDirectories);$(WindowsSdkDir)\lib true %(IgnoreSpecificDefaultLibraries) true NotSet true Ptrace_DllMainCRTStartup 0xC5000000 MachineX64 ================================================ FILE: pin-unpacker/MyPinTool.vcxproj.user ================================================  ================================================ FILE: pin-unpacker/README.md ================================================ # Compilation configuration ## Environment variables 2 environment variables needed : * `PINTOOL_DIR` : pintool installation, so folder `$(PINTOOL_DIR)/source/include/pin` exists * `WIN10SDK_INCLUDE` : SDK installation dir, so `$(WIN10SDK_INCLUDE)/um/windows.h` exists (should me something like `C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0`) Add them through `sysdm.cpl` > Advanced > Envrionment Variables ================================================ FILE: pin-unpacker/Unpacker.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31105.61 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyPinTool", "MyPinTool.vcxproj", "{639EF517-FCFC-408E-9500-71F0DC0458DB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.ActiveCfg = Debug|x64 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x64.Build.0 = Debug|x64 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x86.ActiveCfg = Debug|Win32 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Debug|x86.Build.0 = Debug|Win32 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.ActiveCfg = Release|x64 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x64.Build.0 = Release|x64 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x86.ActiveCfg = Release|Win32 {639EF517-FCFC-408E-9500-71F0DC0458DB}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2F8ECBE6-FF9D-4D3D-B2AB-EC87B9F25AAB} EndGlobalSection EndGlobal ================================================ FILE: pin-unpacker/Upacker.cpp ================================================ #include #include #include #include "pin.H" #include "utils.h" #include "pin_utils.h" #include "IAT.h" #include "export.h" using std::endl; std::ostream * out = &std::cerr; /* GLOBAL VARIABLES */ IAT_table iat_table; char* last_LoadLibrary = NULL; VOID save_results(ADDRINT OEP) { //IAT_print(iat_table, out); export_image(get_main_IMG(), OEP, "export.exe"); IAT_json_save(iat_table, "IAT.json"); exit(0); //FIXME better solution ? continue and do multiple exports (TLS) ? } VOID Fini(INT32 code, VOID *v) { IAT_print(iat_table, out); *out << "DONE" << std::endl; } /* Finds a function RTN object RTN must be closed after use */ RTN FindRoutine(IMG image, std::string name) { for (SYM sym = IMG_RegsymHead(image); SYM_Valid(sym); sym = SYM_Next(sym)) { std::string fname = PIN_UndecorateSymbolName(SYM_Name(sym), UNDECORATION_NAME_ONLY); if (fname == name) { RTN rtn = RTN_FindByAddress(IMG_LowAddress(image) + SYM_Value(sym)); if (RTN_Valid(rtn)) { return rtn; } } } return RTN_Invalid(); } VOID Callback_LoadLibrary(const CONTEXT* ctx, char* lib_name) { ADDRINT saved_EIP = get_stack(ctx, 0); if (in_main_module(saved_EIP)) { // *out << "Callback : LoadLibrary(" << lib_name << ") @ " << int_to_hex(saved_EIP) << endl; last_LoadLibrary = lib_name; IAT_add_library(iat_table, lib_name, get_RVA(saved_EIP)); } } VOID Callback_GetProcAddress(const CONTEXT* ctx, char* funct_name) { ADDRINT RBX = (ADDRINT)PIN_GetContextReg(ctx, REG_RBX); ADDRINT saved_EIP = get_stack(ctx, 0); if (in_main_module(saved_EIP)) { //*out << "Callback : GetProcAddress(" << last_LoadLibrary << ", " << funct_name << ") @ " << int_to_hex(saved_EIP) << endl; //*out << " RBX=" << int_to_hex(RBX) << " (" << int_to_hex(get_RVA(RBX)) << ")" << endl; IAT_add_function(iat_table, last_LoadLibrary, funct_name, get_RVA(RBX), get_RVA(saved_EIP)); //FIXME } } /* Called on DLL loaded by the Application */ VOID Callback_ImageLoad(IMG image, VOID* v) { //*out << "Loading " << IMG_Name(image) << endl; RTN funct_rtn = FindRoutine(image, "LoadLibraryA"); if (RTN_Valid(funct_rtn)) { //*out << "Instrumenting LoadLibraryA in " << IMG_Name(image) << endl; RTN_Open(funct_rtn); RTN_InsertCall(funct_rtn, IPOINT_BEFORE, (AFUNPTR)Callback_LoadLibrary, IARG_CONTEXT, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_Close(funct_rtn); } funct_rtn = FindRoutine(image, "GetProcAddress"); if (RTN_Valid(funct_rtn)) { //*out << "Instrumenting GetProcAddress in " << IMG_Name(image) << endl; RTN_Open(funct_rtn); RTN_InsertCall(funct_rtn, IPOINT_BEFORE, (AFUNPTR)Callback_GetProcAddress, IARG_CONTEXT, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_END); RTN_Close(funct_rtn); } } ADDRINT main_exec_section = 0; bool last_in_exec_section = true; ADDRINT last_ins = 0; VOID Callback_Instruction(INS ins, VOID*) { // check instruction in main module ADDRINT ins_addr = INS_Address(ins); if (in_main_module(ins_addr)) { //FIXME : VirtualAlloc ? SEC ins_sec = Find_Section(ins_addr); if (!SEC_Valid(ins_sec)) { // should never happen inside a module ! *out << "ERROR : instruction in main module, but not in a section ? (" << int_to_hex(ins_addr) << ")" << endl; } else { ADDRINT ins_secaddr = SEC_Address(ins_sec); if (main_exec_section == 0) { main_exec_section = ins_secaddr; //base section address for EntryPoint } else{ if (main_exec_section != ins_secaddr) { if (last_in_exec_section) { *out << "Inter section jump found : RVA " << int_to_hex(get_RVA(ins_addr)) << " called from RVA " << int_to_hex(get_RVA(last_ins)) << endl; save_results(ins_addr); } last_in_exec_section = false; } else { last_in_exec_section = true; } } } } last_ins = ins_addr; } VOID Callback_AppStart(void* ) { //*out << "AppStart callback\n"; } int main(int argc, char *argv[]) { // Initialize PIN library. Print help message if -h(elp) is specified // in the command line or the command line is invalid if( PIN_Init(argc,argv) ) { return 0; } PIN_InitSymbols(); IMG_AddInstrumentFunction(Callback_ImageLoad, NULL); INS_AddInstrumentFunction(Callback_Instruction, NULL); PIN_AddApplicationStartFunction(Callback_AppStart, NULL); PIN_AddFiniFunction(Fini, NULL); // Start the program, never returns PIN_StartProgram(); return 0; } ================================================ FILE: pin-unpacker/export.h ================================================ #pragma once #include #include "pin.H" void export_image(IMG img, ADDRINT OEP, const std::string& path); void export_image_buffer(void* data, size_t size, void* ImageBase, void* RVA_OEP, const std::string& path); ================================================ FILE: pin-unpacker/export_pin.cpp ================================================ /* Pin side for the exports windows.h and pin.H cannot be included simultaneously */ #include #include #include "pin.H" #include "export.h" #include "utils.h" using std::endl; void export_image(IMG img, ADDRINT OEP, const std::string& path) { size_t size = IMG_HighAddress(img) - IMG_LowAddress(img) + 1; char* buffer = (char*) malloc(size); PIN_SafeCopy(buffer, (void*) IMG_LowAddress(img), size); export_image_buffer(buffer, size, (void*)IMG_LowAddress(img), (void*) (OEP - IMG_LowAddress(img)), path); free(buffer); std::cerr << "Module " << IMG_Name(img) << " saved at " << path << endl; } ================================================ FILE: pin-unpacker/export_windows.cpp ================================================ /* Functions of export.h that needs Windows.h included windows.h and pin.H cannot be included simultaneously */ #include #include #include #include //#include "export.h" // this one includes pin, do NOT IMPORT #include "utils.h" using std::endl; size_t pad_size(size_t data, size_t align) { if (data % align == 0) { return 0; } else { return align - (data % align); } } size_t align(size_t data, size_t align) { return data + pad_size(data, align); } /* Saves the sections of a IMG object to a file */ void export_image_buffer(void* data, size_t size, void* ImageBase, void* RVA_OEP, const std::string& path) { IMAGE_DOS_HEADER* p_DOS_HDR = (IMAGE_DOS_HEADER*) data; IMAGE_NT_HEADERS* p_NT_HDR = (IMAGE_NT_HEADERS*)(((char*)p_DOS_HDR) + p_DOS_HDR->e_lfanew); IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)(p_NT_HDR + 1); //Change Optional Header, disable int size warnings #pragma warning(suppress: 4311) #pragma warning(suppress: 4302) p_NT_HDR->OptionalHeader.ImageBase = (ULONGLONG) ImageBase; // #FIXME : 64 bits .... #pragma warning(suppress: 4311) #pragma warning(suppress: 4302) p_NT_HDR->OptionalHeader.AddressOfEntryPoint = (DWORD) RVA_OEP; //Change sections : // all sections have RawSize = VirtualSize // and RawAddress = VirtualAddress for (int i = 0; i < p_NT_HDR->FileHeader.NumberOfSections; ++i) { sections[i].SizeOfRawData = sections[i].Misc.VirtualSize; sections[i].PointerToRawData = sections[i].VirtualAddress; } // Save the result FILE* file = fopen(path.c_str(), "wb"); if (!file) { std::cerr << "ERROR opening output file " << int_to_hex(GetLastError()) << endl; return; } fwrite(data, size, 1, file); fclose(file); } ================================================ FILE: pin-unpacker/pin_utils.cpp ================================================ #include #include "pin_utils.h" #include "utils.h" using std::endl; SEC Find_Section(ADDRINT addr) { //List images loaded in memory IMG img = IMG_FindByAddress(addr); if (IMG_Valid(img)) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { ADDRINT sec_addr = SEC_Address(sec); USIZE sec_size = SEC_Size(sec); if (addr >= sec_addr && addr <= sec_addr + sec_size) { return sec; } } } return SEC_Invalid(); } bool in_main_module(ADDRINT addr) { PIN_LockClient(); IMG img = IMG_FindByAddress(addr); PIN_UnlockClient(); if (!IMG_Valid(img)) { return false; } return IMG_IsMainExecutable(img); } ADDRINT get_RVA(ADDRINT addr) { PIN_LockClient(); IMG img = IMG_FindByAddress(addr); PIN_UnlockClient(); if (!IMG_Valid(img)) { std::cerr << "WARNING : No module found for address " << int_to_hex(addr) << endl; return addr; } return addr - IMG_LowAddress(img); } ADDRINT get_stack(const CONTEXT* ctx, ADDRINT offset) { ADDRINT RSP = (ADDRINT)PIN_GetContextReg(ctx, REG_STACK_PTR); ADDRINT data; PIN_SafeCopy(&data, (void*)(RSP + offset), sizeof(ADDRINT)); return data; } void print_call_stack(const CONTEXT* ctx, std::ostream* out) { ADDRINT RBP = (ADDRINT)PIN_GetContextReg(ctx, REG_RBP); ADDRINT EIP_saved; while (RBP != 0) { PIN_SafeCopy(&EIP_saved, (void*)(RBP + sizeof(ADDRINT)), sizeof(ADDRINT)); *out << " " << int_to_hex(EIP_saved) << endl; PIN_SafeCopy(&RBP, (void*)(RBP), sizeof(ADDRINT)); } } static IMG _main_img = IMG_Invalid(); IMG get_main_IMG() { if (IMG_Valid(_main_img)) { return _main_img; } else { for (IMG img = APP_ImgHead(); IMG_Valid(img); img = IMG_Next(img)) { if (IMG_IsMainExecutable(img)) { _main_img = img; return _main_img; } } } return IMG_Invalid(); } ================================================ FILE: pin-unpacker/pin_utils.h ================================================ #pragma once #include "pin.H" SEC Find_Section(ADDRINT addr); bool in_main_module(ADDRINT addr); ADDRINT get_RVA(ADDRINT addr); ADDRINT get_stack(const CONTEXT* ctx, ADDRINT offset); IMG get_main_IMG(); ================================================ FILE: pin-unpacker/utils.cpp ================================================ #include #include using std::endl; std::string int_to_hex(ADDRINT val) { char buff[33]; sprintf(buff, "0x%llx", val); return std::string(buff); } ================================================ FILE: pin-unpacker/utils.h ================================================ #pragma once #include #include std::string int_to_hex(unsigned long long int val);