Skip to content

Commit

Permalink
Version 1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
ufrisk committed Sep 11, 2019
1 parent bcfd88b commit e35b0ca
Show file tree
Hide file tree
Showing 46 changed files with 222 additions and 108 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The LeechAgent authenticates all incoming connections against membership in the

There is also a possibility to run the LeechAgent in interactive mode (as a normal program). If run in interactive mode a user may also start the LeechAgent in "insecure" mode - which means no authentication or logging at all.

The LeechAgent listens on the port `28473` - please ensure network connectivity for this port in the firewall. Also, if doing live capture ensure that LeechAgent (if running in interactive mode) is started as an administrator.
The LeechAgent listens on the port `tcp/28473` - please ensure network connectivity for this port in the firewall. Also, if doing live capture ensure that LeechAgent (if running in interactive mode) is started as an administrator.

For more information please check the [LeechCore wiki](https://github.com/ufrisk/LeechCore/wiki) and the [blog entry](http://blog.frizk.net/2019/04/LeechAgent.html) about remote live memory capture with the LeechAgent.

Expand Down Expand Up @@ -83,7 +83,9 @@ Start the LeechAgent in interactive mode with DumpIt LIVEKD to allow connecting
Start the LeevhAgent in interactive mode with DumpIt LIVEKD to allow connecting clients to access live memory. Start as elevated administrator. Accept connections from all clients with access to port `tcp/28473` without any form of authentication.
* `DumpIt.exe /LIVEKD /A LeechAgent.exe /C "-interactive -insecure"`


Building:
=========
Pre-built binaries are found together with other supporting files in the files folder. Build instructions are found in the [Wiki](https://github.com/ufrisk/LeechCore/wiki) in the [Building](https://github.com/ufrisk/LeechCore/wiki/Dev_Building) section.

Links:
======
Expand All @@ -107,5 +109,6 @@ v1.2
* LeechCore Windows x86 support. Now Windows x86/x64 and Linux x64 is supported.
* Bug fixes and additional functionality to support LeechAgent.

Latest
v1.3
* Bug fixes.
* Use libusb for FPGA USB access. Contribution by: [Jérémie Boutoille / Synacktiv](https://github.com/tlk-synacktiv).
Binary file modified files/agent/x64/leechagent.exe
Binary file not shown.
Binary file modified files/agent/x64/leechcore.dll
Binary file not shown.
Binary file modified files/agent/x64/leechcorepyc.pyd
Binary file not shown.
Binary file modified files/agent/x64/vmm.dll
Binary file not shown.
65 changes: 49 additions & 16 deletions files/agent/x64/vmmpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# (c) Ulf Frisk, 2018-2019
# Author: Ulf Frisk, pcileech@frizk.net
#
# Header Version: 2.7
# Header Version: 2.8
#

import atexit
Expand Down Expand Up @@ -49,6 +49,20 @@
VMMPY_PLUGIN_EVENT_VERBOSITYCHANGE = 0x01
VMMPY_PLUGIN_EVENT_TOTALREFRESH = 0x02

# WINDOWS REGISTRY contants below:
VMMPY_WINREG_NONE = 0x00
VMMPY_WINREG_SZ = 0x01
VMMPY_WINREG_EXPAND_SZ = 0x02
VMMPY_WINREG_BINARY = 0x03
VMMPY_WINREG_DWORD = 0x04
VMMPY_WINREG_DWORD_BIG_ENDIAN = 0x05
VMMPY_WINREG_LINK = 0x06
VMMPY_WINREG_MULTI_SZ = 0x07
VMMPY_WINREG_RESOURCE_LIST = 0x08
VMMPY_WINREG_FULL_RESOURCE_DESCRIPTOR = 0x09
VMMPY_WINREG_RESOURCE_REQUIREMENTS_LIST = 0x0A
VMMPY_WINREG_QWORD = 0x0B

#------------------------------------------------------------------------------
# VmmPy INITIALIZATION FUNCTIONALITY BELOW:
#------------------------------------------------------------------------------
Expand Down Expand Up @@ -137,6 +151,10 @@ def VmmPy_Initialize(args, is_printf = True, is_verbose = False, is_verbose_extr
VMMPY_OPT_CONFIG_VMM_VERSION_REVISION = 0x40000009 # R
VMMPY_OPT_CONFIG_STATISTICS_FUNCTIONCALL = 0x4000000A # RW - enable function call statistics (.status/statistics_fncall file)

VMMDLL_OPT_WIN_VERSION_MAJOR = 0x40000101 # R
VMMDLL_OPT_WIN_VERSION_MINOR = 0x40000102 # R
VMMDLL_OPT_WIN_VERSION_BUILD = 0x40000103 # R


def VmmPy_ConfigGet(vmmpy_opt_id):
"""Retrieve a configuration setting given a VMMPY_OPT_* option.
Expand Down Expand Up @@ -492,6 +510,36 @@ def VmmPy_WinReg_HiveWrite(va_hive, address, bytes_data):



def VmmPy_WinReg_KeyList(key):
"""Retrieve sub-keys and associated values with the specified registry key.
Keyword arguments:
key -- str: path of registry key to list. May start with address of CMHIVE
in 0xhexadecimal format or HKLM.
return -- dict: of list of subkeys and list of values.
Example:
VmmPy_WinReg_KeyList('HKLM\\HARDWARE') --> {'subkeys': [{'name': 'DEVICEMAP', 'time': 131877368614156304, 'time-str': '2018-11-26 20:14:21 UTC'}, ...], 'values': [...]}
"""
return VMMPYC_WinReg_EnumKey(key)



def VmmPy_WinReg_ValueRead(keyvalue):
"""Read a registry value.
Keyword arguments:
keyvalue -- str: path of registry value to read. May start with address of
CMHIVE in 0xhexadecimal format or HKLM.
return -- dict: of 'type' (value type as in VMMPY_WINREG_*) and 'data' (value data).
Example:
VmmPy_WinReg_ValueRead('HKLM\\SYSTEM\\Setup\\SystemPartition') --> {'type': 1, 'data': b'\\\x00D\x00e\x00v\x00i\x00c\x00e\x00\\\x00H...'}
"""
return VMMPYC_WinReg_QueryValue(keyvalue)



#------------------------------------------------------------------------------
# VmmPy NETWORK FUNCTIONALITY BELOW:
#------------------------------------------------------------------------------
Expand Down Expand Up @@ -598,21 +646,6 @@ def VmmPy_WinGetThunkInfoIAT(pid, module_name, imported_module_name, imported_mo



def VmmPy_WinDecompressPage(va_compressed, len_compressed = 0):
"""Decompress a page stored in the MemCompression process in Windows 10.
Keyword arguments:
va_compressed -- int: the virtual address inside 'MemCompression' where the compressed buffer starts.
len_compressed -- int: optional length of the compressed buffer (leave out for auto-detect).
return -- dict: containing decompressed data and size of compressed buffer.
Example:
VmmPy_WinDecompressPage(0x00000210bfb40000) --> {'c': 456, 'b': b'...'}
"""
return VMMPYC_WinMemCompression_DecompressPage(va_compressed, len_compressed)



#------------------------------------------------------------------------------
# VmmPy UTIL FUNCTIONALITY BELOW:
#------------------------------------------------------------------------------
Expand Down
Binary file modified files/agent/x64/vmmpyc.pyd
Binary file not shown.
Binary file modified files/agent/x86/leechagent.exe
Binary file not shown.
Binary file modified files/agent/x86/leechcore.dll
Binary file not shown.
Binary file modified files/leechcore.dll
Binary file not shown.
2 changes: 1 addition & 1 deletion files/leechcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
// (c) Ulf Frisk, 2018-2019
// Author: Ulf Frisk, pcileech@frizk.net
//
// Header Version: 1.2.0
// Header Version: 1.3.0
//
#ifndef __LEECHCORE_H__
#define __LEECHCORE_H__
Expand Down
Binary file modified files/leechcore.lib
Binary file not shown.
Binary file modified files/leechcore.so
Binary file not shown.
Binary file modified files/leechcorepyc.pyd
Binary file not shown.
Binary file modified files/x86/leechcore.dll
Binary file not shown.
2 changes: 1 addition & 1 deletion files/x86/leechcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
// (c) Ulf Frisk, 2018-2019
// Author: Ulf Frisk, pcileech@frizk.net
//
// Header Version: 1.2.0
// Header Version: 1.3.0
//
#ifndef __LEECHCORE_H__
#define __LEECHCORE_H__
Expand Down
Binary file modified files/x86/leechcore.lib
Binary file not shown.
2 changes: 1 addition & 1 deletion leechagent/leechcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
// (c) Ulf Frisk, 2018-2019
// Author: Ulf Frisk, pcileech@frizk.net
//
// Header Version: 1.2.0
// Header Version: 1.3.0
//
#ifndef __LEECHCORE_H__
#define __LEECHCORE_H__
Expand Down
4 changes: 2 additions & 2 deletions leechagent/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#define STRINGIZE(s) STRINGIZE2(s)

#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_REVISION 2
#define VERSION_MINOR 3
#define VERSION_REVISION 0
#define VERSION_BUILD 0

#define VER_FILE_DESCRIPTION_STR "LeechAgent Memory Acquisition Service"
Expand Down
6 changes: 4 additions & 2 deletions leechcore/device_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ BOOL DeviceFile_MsCrashDumpInitialize()
return TRUE;
}

_Success_(return)
BOOL DeviceFile_GetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
{
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxDeviceMain->hDevice;
Expand Down Expand Up @@ -311,11 +312,12 @@ VOID DeviceFile_Close()
ctxDeviceMain->hDevice = 0;
}

_Success_(return)
BOOL DeviceFile_Open()
{
PDEVICE_CONTEXT_FILE ctx;
ctx = (PDEVICE_CONTEXT_FILE)LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_FILE));
if(!ctx) { return FALSE; }
if(!ctxDeviceMain) { return FALSE; }
if(!(ctx = (PDEVICE_CONTEXT_FILE)LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_FILE)))) { return FALSE; }
if(0 == _strnicmp("file://", ctxDeviceMain->cfg.szDevice, 7)) {
strncpy_s(ctx->szFileName, _countof(ctx->szFileName), ctxDeviceMain->cfg.szDevice + 7, _countof(ctxDeviceMain->cfg.szDevice) - 7);
} else if(0 == _stricmp(ctxDeviceMain->cfg.szDevice, "dumpit")) {
Expand Down
1 change: 1 addition & 0 deletions leechcore/device_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Open a "connection" to the file.
* -- result
*/
_Success_(return)
BOOL DeviceFile_Open();

#endif /* __DEVICE_FILE_H__ */
17 changes: 13 additions & 4 deletions leechcore/device_fpga.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ VOID DeviceFPGA_Close()
ctxDeviceMain->hDevice = 0;
}

_Success_(return)
BOOL DeviceFPGA_GetSetPHY(_In_ PDEVICE_CONTEXT_FPGA ctx, _In_ BOOL isUpdate)
{
DWORD status;
Expand Down Expand Up @@ -472,6 +473,7 @@ VOID DeviceFPGA_SetPerformanceProfile(_Inout_ PDEVICE_CONTEXT_FPGA ctx)
// TLP handling functionality below:
//-------------------------------------------------------------------------------

_Success_(return)
BOOL DeviceFPGA_TxTlp(_In_ PDEVICE_CONTEXT_FPGA ctx, _In_reads_(cbTlp) PBYTE pbTlp, _In_ DWORD cbTlp, BOOL fRdKeepalive, BOOL fFlush)
{
DWORD status;
Expand Down Expand Up @@ -680,7 +682,7 @@ VOID DeviceFPGA_ProbeMEM_Impl(_In_ QWORD qwAddr, _In_ DWORD cPages, _Inout_updat
DeviceFPGA_ProbeMEM_Impl(qwAddr, ctx->perf.PROBE_MAXPAGES, pbResultMap);
cPages -= ctx->perf.PROBE_MAXPAGES;
pbResultMap += ctx->perf.PROBE_MAXPAGES;
qwAddr += ctx->perf.PROBE_MAXPAGES << 12;
qwAddr += (QWORD)ctx->perf.PROBE_MAXPAGES << 12;
}
// prepare
bufMRd.cb = 0;
Expand Down Expand Up @@ -746,6 +748,7 @@ VOID DeviceFPGA_ProbeMEM(_In_ QWORD qwAddr, _In_ DWORD cPages, _Inout_updates_by
}

// write max 128 byte packets.
_Success_(return)
BOOL DeviceFPGA_WriteMEM_TXP(_Inout_ PDEVICE_CONTEXT_FPGA ctx, _In_ QWORD pa, _In_ BYTE bFirstBE, _In_ BYTE bLastBE, _In_ PBYTE pb, _In_ DWORD cb)
{
DWORD txbuf[36], i, cbTlp;
Expand Down Expand Up @@ -782,6 +785,7 @@ BOOL DeviceFPGA_WriteMEM_TXP(_Inout_ PDEVICE_CONTEXT_FPGA ctx, _In_ QWORD pa, _I
return DeviceFPGA_TxTlp(ctx, pbTlp, cbTlp, FALSE, FALSE);
}

_Success_(return)
BOOL DeviceFPGA_WriteMEM(_In_ QWORD pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb)
{
PDEVICE_CONTEXT_FPGA ctx = (PDEVICE_CONTEXT_FPGA)ctxDeviceMain->hDevice;
Expand Down Expand Up @@ -813,6 +817,7 @@ BOOL DeviceFPGA_WriteMEM(_In_ QWORD pa, _In_reads_(cb) PBYTE pb, _In_ DWORD cb)
return DeviceFPGA_TxTlp(ctx, NULL, 0, FALSE, TRUE) && result; // Flush and Return.
}

_Success_(return)
BOOL DeviceFPGA_ListenTlp(_In_ DWORD dwTime)
{
PDEVICE_CONTEXT_FPGA ctx = (PDEVICE_CONTEXT_FPGA)ctxDeviceMain->hDevice;
Expand All @@ -826,12 +831,14 @@ BOOL DeviceFPGA_ListenTlp(_In_ DWORD dwTime)
return TRUE;
}

_Success_(return)
BOOL DeviceFPGA_WriteTlp(_In_ PBYTE pbTlp, _In_ DWORD cbTlp)
{
PDEVICE_CONTEXT_FPGA ctx = (PDEVICE_CONTEXT_FPGA)ctxDeviceMain->hDevice;
return DeviceFPGA_TxTlp(ctx, pbTlp, cbTlp, FALSE, TRUE);
}

_Success_(return)
BOOL DeviceFPGA_GetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
{
PDEVICE_CONTEXT_FPGA ctx = (PDEVICE_CONTEXT_FPGA)ctxDeviceMain->hDevice;
Expand Down Expand Up @@ -881,6 +888,7 @@ BOOL DeviceFPGA_GetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
return FALSE;
}

_Success_(return)
BOOL DeviceFPGA_SetOption(_In_ QWORD fOption, _In_ QWORD qwValue)
{
PDEVICE_CONTEXT_FPGA ctx = (PDEVICE_CONTEXT_FPGA)ctxDeviceMain->hDevice;
Expand Down Expand Up @@ -917,8 +925,10 @@ BOOL DeviceFPGA_SetOption(_In_ QWORD fOption, _In_ QWORD qwValue)
return FALSE;
}

_Success_(return)
BOOL DeviceFPGA_CommandData(_In_ ULONG64 fOption, _In_reads_(cbDataIn) PBYTE pbDataIn, _In_ DWORD cbDataIn, _Out_writes_opt_(cbDataOut) PBYTE pbDataOut, _In_ DWORD cbDataOut, _Out_opt_ PDWORD pcbDataOut)
{
if(pcbDataOut) { *pcbDataOut = 0; }
switch(fOption) {
case LEECHCORE_COMMANDDATA_FPGA_WRITE_TLP:
return (cbDataIn >= 12) && pbDataIn && DeviceFPGA_WriteTlp(pbDataIn, cbDataIn);
Expand All @@ -933,24 +943,22 @@ VOID DeviceFPGA_Open_ParseParams(_Out_writes_(4) PDWORD dwOptions)
CHAR _szBuf[MAX_PATH];
DWORD i, j;
LPSTR sz;
ZeroMemory(dwOptions, 4 * sizeof(DWORD));
if(0 == _strnicmp("fpga://", ctxDeviceMain->cfg.szDevice, 7)) {
strcpy_s(_szBuf, _countof(_szBuf), ctxDeviceMain->cfg.szDevice);
sz = _szBuf + 7;
for(i = 7, j = 0; i < _countof(_szBuf); i++) {

if(':' == _szBuf[i]) {
_szBuf[i] = 0;
dwOptions[j] = atoi(sz);
if(++j == 4) { return; }
sz = _szBuf + i + 1;
continue;
}

if('\0' == _szBuf[i]) {
dwOptions[j] = atoi(sz);
return;
}

}
}
}
Expand All @@ -960,6 +968,7 @@ VOID DeviceFPGA_Open_ParseParams(_Out_writes_(4) PDWORD dwOptions)
#define OPTION_DELAY_WRITE 2
#define OPTION_DELAY_PROBE 3

_Success_(return)
BOOL DeviceFPGA_Open()
{
LPSTR szDeviceError;
Expand Down
1 change: 1 addition & 0 deletions leechcore/device_fpga.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Open a connection to the PCILeech flashed FPGA device.
* -- result
*/
_Success_(return)
BOOL DeviceFPGA_Open();

#endif /* __DEVICE_FPGA_H__ */
10 changes: 8 additions & 2 deletions leechcore/device_hvsavedstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ VOID DeviceHvSavedState_Close()
ctxDeviceMain->hDevice = 0;
}

_Success_(return)
BOOL DeviceHvSavedState_Open_OpenHvHandle(PHVSAVEDSTATE_CONTEXT ctx)
{
HRESULT hr;
Expand All @@ -358,6 +359,7 @@ BOOL DeviceHvSavedState_Open_OpenHvHandle(PHVSAVEDSTATE_CONTEXT ctx)
return TRUE;
}

_Success_(return)
BOOL DeviceHvSavedState_Open_MemMap(PHVSAVEDSTATE_CONTEXT ctx)
{
HRESULT hr;
Expand Down Expand Up @@ -388,6 +390,7 @@ BOOL DeviceHvSavedState_Open_MemMap(PHVSAVEDSTATE_CONTEXT ctx)
return TRUE;
}

_Success_(return)
BOOL DeviceHvSavedState_Init(PHVSAVEDSTATE_CONTEXT ctx) {
VIRTUAL_PROCESSOR_REGISTER reg;

Expand Down Expand Up @@ -439,6 +442,7 @@ BOOL DeviceHvSavedState_Init(PHVSAVEDSTATE_CONTEXT ctx) {
return TRUE;
}

_Success_(return)
BOOL DeviceHvSavedState_Open_InitializeDll(PHVSAVEDSTATE_CONTEXT ctx)
{
const LPSTR FN_LIST[] = { "ApplyPendingSavedStateFileReplayLog", "GetArchitecture", "GetGuestPhysicalMemoryChunks", "GetGuestRawSavedMemorySize", "GetPagingMode", "GetRegisterValue", "GetVpCount", "GuestPhysicalAddressToRawSavedMemoryOffset", "GuestVirtualAddressToPhysicalAddress", "LoadSavedStateFile", "LoadSavedStateFiles", "LocateSavedStateFiles", "ReadGuestPhysicalAddress", "ReadGuestRawSavedMemory", "ReleaseSavedStateFiles" };
Expand Down Expand Up @@ -478,10 +482,12 @@ BOOL DeviceHvSavedState_GetOption(_In_ QWORD fOption, _Out_ PQWORD pqwValue)
return FALSE;
}

_Success_(return)
BOOL DeviceHvSavedState_Open()
{
PHVSAVEDSTATE_CONTEXT ctx = (PHVSAVEDSTATE_CONTEXT)LocalAlloc(LMEM_ZEROINIT, sizeof(HVSAVEDSTATE_CONTEXT));
if(!ctx) { return FALSE; }
PHVSAVEDSTATE_CONTEXT ctx = NULL;
if(!ctxDeviceMain) { return FALSE; }
if(!(ctx = (PHVSAVEDSTATE_CONTEXT)LocalAlloc(LMEM_ZEROINIT, sizeof(HVSAVEDSTATE_CONTEXT)))) { return FALSE; }
if(!DeviceHvSavedState_Open_InitializeDll(ctx)) {
vprintf(
"DEVICE: FAILED: Hyper-V Saved State API DLL 'vmsavedstatedumpprovider.dll' was \n" \
Expand Down
1 change: 1 addition & 0 deletions leechcore/device_hvsavedstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Open a connection to the USB3380 PCILeech flashed device.
* -- result
*/
_Success_(return)
BOOL DeviceHvSavedState_Open();

#endif /* __DEVICE_HVSAVEDSTATE_H__ */
Loading

0 comments on commit e35b0ca

Please sign in to comment.