18 January, 2017
The unexpected behavior of std::mutex
26 October, 2016
Trampolines for hooking
Here I would like to show all variants of trampolines which I know.
32-bits Intel architecture (x86):
; 5 code bytes ; relative addressing ; no registers modification ; EIP+78563412h == 0019fa9ah+78563412h == 78702each 0019fa95 e912345678 jmp 78702each 0019fa9a
; 6 code bytes ; absolute addressing ; no registers modification 0019fa95 6812345678 push 78563412h 0019fa9a c3 ret 0019fa9b
; 8 code bytes ; absolute addressing ; EAX value lost 0019fa95 c7c012345678 mov eax,78563412h 0019fa9b ffe0 jmp eax 0019fa9d
; 6 code bytes + 4 data bytes ; absolute addressing ; no registers modification ; data in execution code ; absolute data addressing 0019fa95 ff259bfa1900 jmp dword ptr ds:[19FA9Bh] 0019fa9b 12345678 dd 78563412h 0019fa9f
64-bits AMD architecture (amd64 / x86_64 / x64):
; 14 code bytes ; absolute addressing ; no registers modification 00000000`0014f605 6812345678 push 78563412h 00000000`0014f60a c74424049abcdef0 mov dword ptr [rsp+4],0F0DEBC9Ah 00000000`0014f612 c3 ret 00000000`0014f613
; 6 code bytes ; absolute addressing in lower 4Gb ; no registers modification 00000000`0014f605 6812345678 push 78563412h 00000000`0014f60a c3 ret 00000000`0014f60b
; 12 code bytes ; absolute addressing ; change RAX (return value register) 00000000`0014f605 48b8123456789abcdef0 mov rax,0F0DEBC9A78563412h 00000000`0014f60f ffe0 jmp rax 00000000`0014f611
; 13 code bytes ; absolute addressing ; change R11 (temporary register) 00000000`0014f605 49bb123456789abcdef0 mov r11,0F0DEBC9A78563412h 00000000`0014f60f 41ffe3 jmp r11 00000000`0014f612
; 6 code bytes + 8 data bytes in range RIP±2Gb ; absolute addressing ; no registers modification ; data in execution code ; relative data addressing ; RIP+00000000h == 00000000`0014f60bh+00000000h == 00000000`0014f60bh 00000000`0014f605 ff2500000000 jmp qword ptr [00000000`0014f60bh] 00000000`0014f60b 123456789abcdef0 dq 0F0DEBC9A78563412h 00000000`0014f613
; 5 code bytes ; relative addressing RIP±2Gb ; no registers modification ; EIP+78563412h == 00000000`0014f60ah+78563412h == 00000000`786b2a1ch 00000000`0014f605 e912345678 jmp 00000000`786b2a1ch 00000000`0014f60a
P.S. Please let me know if you have new variant.
09 July, 2016
Solve the "no GUID has been associated with this object" compiler error for __uuidof in templates instantinations
As you know WinRT has C++ interfaces ABI::Windows::Foundation::Collections::IIterable and ABI::Windows::Foundation::Collections::IIterable to make iteration in collections universal. This is the very good idea, but you got interfaces with templates: (see windows.foundation.collections.h):
namespace ABI {
namespace Windows {
namespace Foundation {
namespace Collections {
template <class T>
struct IIterator
: IIterator_impl<T>
, detail::not_yet_specialized<IIterator<T>>
{
};
template <class T>
struct IIterable
: IIterable_impl<T>
, detail::not_yet_specialized<IIterable<T>>
{
};
template <class T, bool isStruct>
struct IIterator_impl : IInspectable
{
private:
typedef typename Windows::Foundation::Internal::GetAbiType<T>::type T_abi;
typedef typename Windows::Foundation::Internal::GetLogicalType<T>::type T_logical;
public:
typedef T T_complex;
virtual /* propget */ HRESULT STDMETHODCALLTYPE get_Current(_Out_ T_abi *current) = 0;
virtual /* propget */ HRESULT STDMETHODCALLTYPE get_HasCurrent(_Out_ boolean *hasCurrent) = 0;
virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ boolean *hasCurrent) = 0;
virtual HRESULT STDMETHODCALLTYPE GetMany(_In_ unsigned capacity, _Out_writes_to_(capacity,*actual) T_abi *value, _Out_ unsigned *actual) = 0;
};
template <class T>
struct IIterable_impl : IInspectable
{
private:
typedef typename Windows::Foundation::Internal::GetAbiType<T>::type T_abi;
typedef typename Windows::Foundation::Internal::GetLogicalType<T>::type T_logical;
public:
typedef T T_complex;
virtual HRESULT STDMETHODCALLTYPE First(_Outptr_result_maybenull_ IIterator<T_logical> **first) = 0;
};
}}}}
18 September, 2015
How to load strong named assembly from the location out of application base directory to new application domain
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="YYY" culture="" publicKeyToken="0123456789012345" />
<codeBase version="K.L.M.N" href="file:///X:/XXX/YYY.DLL" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ZZZ" culture="" publicKeyToken="1234567890123456" />
<codeBase version="A.B.C.D" href="file:///X:/XXX/ZZZ.DLL" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
And set it to AppDomainSetup.ConfigurationFile:
var appDomain = AppDomain.CreateDomain("MyDomain", null, new AppDomainSetup
{
ConfigurationFile = configFile
});
07 September, 2014
Powershell script to close mercurial branches older then 60 days
# Close old branches for Mercurial
# Copyright (C) 2014 Mikhail Pilin
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if ($PSVersionTable.PSVersion.Major -lt 3) {
throw "PS Version $($PSVersionTable.PSVersion) is below 3.0."
}
Set-StrictMode -Version Latest
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$script:VerbosePreference = "Continue"
$encoding = "cp866"
[System.TimeSpan]$alive = [System.TimeSpan]::FromDays(60)
[System.DateTime]$now = [System.DateTime]::Now
[System.Object]$current = & hg parent --encoding $encoding -T "{node} {branch}" | ForEach-Object {
$result = $_ | Select-Object -Property node, name
$parts = $_.Split(' ', 2)
$result.node = $parts[0]
$result.name = $parts[1]
$result
} | Select-Object
Write-Host "Current branch: " -nonewline
Write-Host -foregroundcolor gray $current.name
[System.Object[]]$branches = @(& hg head --encoding $encoding -T "{date(date,'%Y%m%d%H%M%S')} {node} {branch}\n" | ForEach-Object {
$result = $_ | Select-Object -Property date, node, name
$parts = $_.Split(' ', 3)
[System.DateTime]$result.date = [System.DateTime]::ParseExact($parts[0], "yyyyMMddHHmmss", [System.Globalization.CultureInfo]::InvariantCulture)
$result.node = $parts[1]
$result.name = $parts[2]
$result
} | Where-Object { $now - $_.date -gt $alive } | Sort-Object -property date)
function EscapeBranchName
{
Param([System.String]$name)
$name.Replace('"', '\"')
}
if ($branches.Length -eq 0) { Write-Host "No old branches were detected" } else {
Write-Host "Closing $($branches.Length) old branches:"
$branches | ForEach-Object {
Write-Host "[$([System.String]::Format("{0:%d}", $now - $_.date)) days] " -nonewline
Write-Host -foregroundcolor gray $_.name
& hg debugsetparent $_.node | Out-Null
if ($LastExitCode -ne 0) { Write-Warning "Failed to set node (exit code $LastExitCode)." } else {
& hg branch $(EscapeBranchName $_.name) | Out-Null
if ($LastExitCode -ne 0) { Write-Warning "Failed to set branch (exit code $LastExitCode)." } else {
& hg commit --close-branch -X * -m $("The branch was not used for {0:%d} days and closed automatically." -f ($now - $_.date)) | Out-Null
if ($LastExitCode -ne 0) { Write-Warning "Failed to commit (exit code $LastExitCode)." }
}
}
}
Write-Host "Restore current branch: " -nonewline
Write-Host -foregroundcolor gray $current.name
& hg debugsetparent $current.node | Out-Null
if ($LastExitCode -ne 0) { Write-Warning "Failed to set node (exit code $LastExitCode)." } else {
& hg branch $(EscapeBranchName $current.name) | Out-Null
if ($LastExitCode -ne 0) { Write-Warning "Failed to set branch (exit code $LastExitCode)." }
}
}
02 March, 2014
Decoding the parameters of a thrown C++ exception (0xE06D7363)
I have a lot questions after reading the post about decoding structural exception 0xE06D7363 from "The Old New Thing". I like computer magic like that: take address from here add the constant two and half time and you get it. However, this magic don't help to understand how it really works and what happened if I do that. So, following code from CRT kill all magic.
06 November, 2013
How to install .NET Framework 1.1 on Windows 8.1
After update from Windows 8.0 to Windows 8.1 I found that .NET Framework 1.1 was unexpectedly disappeared. Here I give you the tested way to return it back:
- Download .NET Framework Cleanup Tool (product guide here) from following locations: here or here
- Unzip and run following commands:
cleanup_tool.exe /q:a /c:"cleanup.exe /p .NET Framework 1.0" cleanup_tool.exe /q:a /c:"cleanup.exe /p .NET Framework 1.1"
- Following instructions were taken from here:
- Create a new folder named DotNet in C:\ drive. (The path i used was C:\DotNet)
- Download Microsoft .NET Framework 1.1 Redistributable Package (dotnetfx.exe). Make sure the setup file is saved as dotnetfx.exe.
- Download Microsoft .NET Framework 1.1 Service Pack 1 (NDP1.1sp1-KB867460-X86.exe). Rename the file to dotnetfxsp1.exe.
- Copy both installation files into the same directory (i.e. C:\DotNet),.
- Open Command Prompt as Administrator.
- Change to the directory where the two installation files are stored, ie C:\DotNet.
- Run the following commands one by one:
dotnetfx.exe /c:"msiexec.exe /a netfx.msi TARGETDIR=C:\DotNet" dotnetfxsp1.exe /Xp:C:\DotNet\netfxsp.msp msiexec.exe /a c:\DotNet\netfx.msi /p c:\DotNet\netfxsp.msp
- Install Microsoft .Net Framework 1.1 with slipstreamed Service Pack 1 by running netfx.msi from the working folder.
Good luck!
07 June, 2013
Tricky macro to add file name and line number in C++ operator new
Header file:
#if defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
extern __declspec(thread) char const * t_File;
extern __declspec(thread) int t_Line;
inline void * __CRTDECL operator new (size_t const size) { return ::operator new (size, _NORMAL_BLOCK, t_File, t_Line); }
inline void * __CRTDECL operator new[](size_t const size) { return ::operator new[](size, _NORMAL_BLOCK, t_File, t_Line); }
#define new (t_File = __FILE__, t_Line = __LINE__, false) ? nullptr : new
#endif
Source file:
#if defined(_DEBUG) __declspec(thread) char const * t_File = "???"; __declspec(thread) int t_Line = 0; #endif
This macro doesn't work with direct operator call like operator new(...) in code.
P.S. This macro tested only on Visual Studio 2012