skip to Main Content

How to make an offline copy of a website

To create an offline browseable copy of a website you can use the tool wget.
I will guide you through the steps on how to create a offline copy based on your needs.

Download the website

wget --mirror --no-check-certificate -e robots=off --timestamping --recursive --level=inf \
--no-parent --page-requisites --convert-links --adjust-extension --backup-converted -U Mozilla \
--reject-regex feed -R '*.gz, *.tar, *.mp3, *.zip, *.flv, *.mpg, *.pdf'

Change into the directory of the offline copy:

cd www.test.domain

Clean up temp files

wget craetes some temp files, remove them:

find . -type f -name '*.orig' | xargs -n1 rm -f

Optimize images

If you want, you can convert JPEG images to a lower quality to save disk space:

find . -iname '*.jpg' | xargs -n1 mogrify -strip -quality 20

PNG files can be converted to JPEG files, but you have to keep the same filename with png ending to not break the offline website.

find . -name '*.png' | xargs -n1 mogrify -strip -quality 20 -format jpg
find . -name '*.PNG' | xargs -n1 mogrify -strip -quality 20 -format jpg
# rename the png files that got converted to jpg back to png
find . -name '*.png' -exec sh -c 'mv `dirname "$0"`/`basename "$0" .png`.jpg $0' '{}' \;
find . -name '*.PNG' -exec sh -c 'mv `dirname "$0"`/`basename "$0" .PNG`.jpg $0' '{}' \;

How to install Ubuntu on an Acer C710 Chromebook

To get Ubuntu running on your Acer C710 Chromebook you have the the choice between running it in a chroot environment next to the running Chrome OS or install it in a new partition and boot directly the Ubuntu kernel. I used the 2. option in the past but had some issues with drivers and updating the system. My recommendation is to use Install option 1.


If you want to start fresh or your system does not boot anymore, follow the instructions at to recover your system.

Developer mode

To install Ubuntu, the Chromebook needs to be in developer mode. The download part of the installation may be speed up by using a LAN cable instead of Wi-Fi.

  • Switch off the Chromebook
  • Hold down the ESC and F3 keys and poke the Power button
  • After ca 5s press Ctrl-D and on the appearing screen confirm the switch into developer mode by pressing Return

Install Ubuntu in a chroot to use it parallel to Chrome OS at the same time

  • Download
  • Press Ctrl+Alt+T to open a shell in the browser and enter the command shell
  • Install crouton, remove -e if you do not want to encrypt the installation
sh ~/Downloads/crouton -e -r trusty -t xiwi,xfce

To get into Ubuntu, run:

sudo enter-chroot

Alternative Install option: Install Ubuntu on a partition to boot from

  • Boot into Chrome OS, configure the network but do not log in
  • To get to the console mode, press CTRL+ALT+F2
  • Login as user chronos

The modern chrx installer does not support the C710 yet, only C720 and other models. Once the support is added, it might be worth trying out GalliumOS. So for now you have to use the old ChrUbuntu installer to install Ubuntu:

curl -LOs && sudo bash s9ryd

Enter a size for the Ubuntu partition size and confirm. The Chromebook will now reboot and restore Chrome OS into the new partitioned system.

Repeat the above steps from getting into console step, but this time you can specify a parameter to the execution of the installer script. You can give a specific Ubuntu destribution as parameter (kubuntu-desktop, lubuntu-desktop, xubuntu-desktop, edubuntu-desktop or ubuntu-standard), I recommend using lubuntu-desktop because it uses less RAM than the other ones with a GUI. Execute:

curl -LOs && sudo bash s9ryd

This will install the latest Ubuntu LTS release. After the installation is done and you reboot, you will be inside Ubuntu. You can login with user user and password user. When the system booted correctly, you can set to boot Ubuntu by default by executing:

sudo cgpt add -i 6 -P 5 -S 1 /dev/sda

If you want to boot into Chrome OS again, execute:

sudo cgpt add -i 6 -P 0 -S 1 /dev/sda

How to get started with Golang

There are multiple resources available to learn Go. The Go Playground allows you to write code in the browser and test it, without that you need to install anything locally.

Golang Resources

Free books

Example code

If you want to start developing Golang more seriously, you will not get around using an IDE that offers you autocompletion and also Debugging capabilities.


Install the Golang runtime environment by following the instructions at If you are installing Go on Windows you can use the MSI Installer which also sets environment variables in the system. These environment variables are needed to access go from the command line.


go get -u
go get -u
go get -u

How to setup a development environment with Docker

Docker installation:

Docker runs natively on Linux, to use it on Mac OS or Windows you need to run it in a Virtual Machine. For this blog entry I will use running docker on Mac OS in VirtualBox. I recommend using brew to install it because it also takes care of updating it.

brew install docker docker-compose docker-machine
brew cask install virtualbox

If you want to do it by hand instead, follow the Tutorial at or

Start Docker:

After you installed docker-machine you need to create a Virtual Machine that runs the docker daemon inside a tiny Linux guest:

docker-machine create --driver=virtualbox --virtualbox-memory 2048 --virtualbox-cpu-count 2 dev

The output will look like:

Creating CA: /Users/cornel/.docker/machine/certs/ca.pem
Creating client certificate: /Users/cornel/.docker/machine/certs/cert.pem
Image cache does not exist, creating it at /Users/cornel/.docker/machine/cache...
No default boot2docker iso found locally, downloading the latest release...
Downloading to /Users/cornel/.docker/machine/cache/boot2docker.iso...
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env dev

Verify that the Virtual Machine is running:

docker-machine ls

The output of the command should show the generated Virtual Machine:

NAME   ACTIVE   DRIVER       STATE     URL                         SWARM
dev             virtualbox   Running   tcp://

Configure shell environment:

The local docker client that will access the docker daemon inside the Virtual Machine needs to know how it should access it. docker-machine can show you the needed configuration, execute:

docker-machine env dev

The command output depends on the detected shell that you used to execute the command:

set -x DOCKER_HOST "tcp://";
set -x DOCKER_CERT_PATH "/Users/cornel/.docker/machine/machines/dev";
# Run this command to configure your shell:
# eval (docker-machine env dev)

You can execute the given commands by hand or output the configuration file of your shell:

  • bash shell: ~/.bash_profile
  • fish shell: ~/.config/fish/

To test the setup, list all running docker containers with the command:

docker ps

Working with docker containers:

To see which docker containers are currently running:

docker ps

To connect into a container, use the container name shown by docker ps and the following command. Press enter after the command is executed once to see the actual shell. You have to exit the shell by pressing Ctrl+P+Q or closing the terminal, using Ctrl+D or exit as a command will shut down the container.

docker attach <containername>

A different way to attach to a container where you can exit the shell in a normal way:

docker exec -it <containername> /bin/bash

To see the log output from a container:

docker logs <containername>

You can watch the log output of a container with:

docker logs --tail=10 -f <containername>


Mounting a directory from outside into the docker container has performance issues on Mac OS:

Anti-Adblock-Killer Guide to fight Anti-Adblock

Anti-Adblock Introdution

If you use an Adblock technology like uBlock, you sometimes see an Anti-Adblock technology on a website that blocks you from accessing the website content. A famous example recently is I will use a website as an example to show how you can defeat that by creating a custom whitelist rule that will fight the Anti-Adblock but still disable the Advertisements and Tracking. You can call it an Anti-Anti-Adblock or Anti-Adblock-Killer.

Create an Anti-Adblock-Killer for an example website

The example website for this tutorial is that shows a nag screen. When you open the website with Adblock enabled, you receive a message like this:

Anti-Adblock Nag Screen

Open the developer tools (by pressing F12 on Windows for Chrome), click the magnifier to inspect the element and click on the dialog that shows the Anti-Adblock message.

Anti-Adblock Nag Screen Div

The sourcecode shows the div that displays this message. The name indicates that the div id is random, refreshing the page and inspecting the div again proofs that. Therefore a black or white-listing based on the div id would not work. Now search for the id of the div in the code by pressing Ctrl+F. One of the matches is:

Anti-Adblock Nag Screen JavaScript

As you can see by the code and name of the canRunAds variable, it is used to determine if the user can show Ads or uses an Adblocker. Searching for canRunAds reveals no code location that sets it, therefore it must be set by an external script (If the code to set it is not obfuscated of course). Open the Network tab of the developer tools and refresh the page. You will now see all network requests that got blocked by the Adblocker marked red.

Anti-Adblock Network View Developer Tools

Right click on each of the blocked scripts and select Open in new tab. The url reveals an interesting script:

var canRunAds = true;

Now all we need to do is whitelist this specific url in uBlock. Open the uBlock settings, select My rules, click Edit below Temporary rules and insert a new line: script allow

Save the whitelist rules, refresh the website and voila the nag screen is gone and shows no Ads.

Update the Anti-Adblock-Killer

Update 2015-08-2: The website Anti-Adblock code changed and the solution above does not work anymore. A look into the code of the website reveals the new added JavaScript code:

var script = document.createElement('script');
    script.onerror = function(){
        script.onerror = null;
        _gaq.push(['_trackEvent', 'adblock popup', "show popup", document.location+""]);
    script.src = "";

This code uses the window.onerror function to catch failed http request which in our case is the blocked the Ad script. In the source code of the nag screen you can see that is uses the css class headline. If you search for it in the html you will see that it is only used in the nag screen. That allows us to use that class to find the nag screen with a jquery selector and from there to traverse up the DOM tree to find the main div of the nag screen that has a random id. Install Tampermonkey for Chrome or Greasemonkey for Firefox and add a new user script with the following content:

// ==UserScript==
// @name Anti-Adblock Killer
// @require
// @namespace
// @version      1.0
// @description  Removes the nag screen on when using an ad-blocker
// @author       CornelK
// @match*
// @grant        none
// ==/UserScript==

var script = document.createElement('script');
script.src = "";


Refresh the site and voila, the nag screen is gone again (for now).

Mac OS X Development Setup Guide

This blog entry contains a list of applications and instructions how to install them for setting up a Mac as a development machine. Some applications need to be installed manually, for the rest I recommend using Homebrew - a package manager for Mac OS X. If you plan to start with a fresh Mac OS X install, follow the instructions on Apple Support.

Setting up brew

Open a terminal and install the Command Line Tools for Xcode that are needed for the Homebrew installation

xcode-select --install

Install Homebrew:

ruby -e "$(curl -fsSL"

Disable Analytics being sent to Google:

brew analytics off

To extend the amount of available packages (especially GUI applications), also install homebrew-cask:

brew install caskroom/cask/brew-cask

Check if the system setup is correct:

brew doctor

On my fresh system install it found the problem that /usr/local/etc isn't writeable. I fixed it by running:

sudo chown `whoami` /usr/local/etc

Rerun the doctor command again to see if all problems are fixed now. On success it shows:

Your system is ready to brew.

Now you are ready to install all other applications using a simple command on the shell. Brew also takes care of updating them.

Update existing applications

Replace the installed applications by newer versions:

brew install bash ctags git python
brew tap homebrew/dupes
brew install openssh



brew cask install skype


Go Golang programming language

brew install go

Graphviz Graph Visualization Software useful for Golangs profiling visualization

brew install graphviz


brew install mercurial

Node.js and useful apps for it

brew install nodejs
brew install flow gradle watchman

Android SDK and Genymotion

brew install android-sdk
brew cask install android-studio
brew install genymotion

Python 3

brew install python3
pip2 install virtualenv
pip3 install virtualenv

Visual Studio Code - IDE

brew cask install visual-studio-code
code --install-extension DavidAnson.vscode-markdownlint
code --install-extension PeterJausovec.vscode-docker
code --install-extension casian.plsql
code --install-extension codezombiech.gitignore
code --install-extension donjayamanne.python
code --install-extension joaompinto.asciidoctor-vscode
code --install-extension lukehoban.Go
code --install-extension mitaki28.vscode-clang
code --install-extension ms-vscode.cpptools
code --install-extension robertohuertasm.vscode-icons
code --install-extension vscodevim.vim
code --install-extension wayou.vscode-todo-highlight
code --install-extension yzane.markdown-pdf
code --install-extension zxh404.vscode-proto3

Protocol buffers version 3 protoc compiler

brew install protobuf

neovim - modern VIM version

brew install neovim/neovim/neovim
pip2 install neovim
pip3 install neovim
brew install rogual/neovim-dot-app/neovim-dot-app
brew linkapps neovim-dot-app

Meld - A visual Two- and three-way visual diff and merge tool

brew install homebrew/gui/meld


fish - User-friendly command line shell

brew cask install fish

iTerm 2 - Replacement for the built in Terminal

brew cask install iterm2

appcleaner - Uninstall unwanted apps

brew cask install appcleaner

KeePassX - Password manager

brew cask install keepassx

NTFS-3G - Read-Write NTFS Driver

brew cask install osxfuse
brew tap homebrew/fuse
brew install ntfs-3g
sudo mv /sbin/mount_ntfs /sbin/mount_ntfs.original
sudo ln -s /usr/local/sbin/mount_ntfs /sbin/mount_ntfs

VeraCrypt - disk encryption

brew cask install veracrypt

Commander One - dual pane file manager as Finder replacement

brew cask install commander-one


f.lux - makes the color of your computer's display adapt to the time of day, warm at night and like sunlight during the day

brew cask install flux

KeepingYouAwake - Menu bar utility to prevent your Mac from going into sleep mode

brew cask install keepingyouawake

htop - an interactive process viewer

brew install htop

Shortcat - Faster clicking without using the mouse

brew cask install shortcat


docker - lightweight software container isolation, client

brew cask install docker
mkdir -p ~/.config/fish/completions
curl -o ~/.config/fish/completions/

VirtualBox - operating system virtualization

brew cask install virtualbox

Docker Compose - define and run multi-container applications with docker

brew install docker-compose

Wine - runs Windows applications on non Windows systems

brew cask install xquartz
brew install wine winetricks


Google Chrome - My default browser to replace Safari

brew cask install google-chrome


brew cask install firefox

Command-line tools for network access

brew install axel curl ncftp nmap wget

VPN / Proxy tools

brew install corkscrew
brew cask install tunnelblick

Syncthing - Decentralized file sync

brew install syncthing
ln -sfv /usr/local/opt/syncthing/*.plist ~/Library/LaunchAgents

dnscrypt - Circumvent DNS blocking of ISPs

brew cask install dnscrypt


VLC - Multimedia player for videos

brew cask install vlc

VOX - Slim audio player

brew cask install vox

XnView MP - Image viewer

brew cask install xnviewmp

ImageMagick - Image processing

brew install imagemagick --with-librsvg

RawTherapee - Photo editor

brew cask install rawtherapee

GIMP - Image editor

brew cask install gimp

keycastr - keystroke visualizer

brew cask install keycastr

HandBrake - video converter

brew cask install handbrake


LibreOffice - Free Office suite

brew cask install libreoffice

Haroopad - Markdown editor

brew cask install haroopad

Pandoc - Universal document converter

brew install pandoc

Ghostscript - PostScript and PDF utilities

brew install ghostscript

calibre - e-book library management

brew cask install calibre

Fish shell configuration

Set fish as your default shell:

chsh -s /usr/local/bin/fish

Update fish tab completion data by starting a new Terminal with fish and executing:


Install oh-my-fish plugin management:

curl -L | fish

Install plugins based on your preference:

omf install brew extract tab

Edit the ~/.config/omf/ and adjust to your own needs:

if status --is-interactive

set -gx fish_greeting ''
set -gx GOPATH ~/gocode
set -gx PATH $PATH $GOPATH/bin


Git configuration

# Ignore file mode differences
git config --global core.fileMode false
# Better cross-platform line ending handling
git config --global core.autocrlf input
# fix go get redirect errors
git config --global http. true

Adjust Mac OS X default settings

# Disable Game Center
launchctl unload -w /System/Library/LaunchAgents/
# Avoid creation of .DS_Store files on network volumes
defaults write DSDontWriteNetworkStores -bool true
# Disable autocorrect
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false
# Enable dark mode
defaults write NSGlobalDomain AppleInterfaceStyle Dark; killall Dock
# Ask for password screen lock delay
defaults -currentHost write askForPasswordDelay -int 10
# Allow app installation from any source
sudo spctl --master-disable

Tune system settings

brew install m-cli
m dock magnification NO
m dock prune
m finder showhiddenfiles YES
m finder showextensions YES
m finder showdesktop YES
sudo m gatekeeper disable
m notification showcenter NO

Remove not needed Applications

sudo rm -rf /Applications/
sudo rm -rf /Applications/
sudo rm -rf /Applications/
sudo rm -rf "/Library/Application Support/GarageBand"
sudo rm -rf "/Library/Application Support/Logic"
sudo rm -rf "/Library/Audio/Apple Loops"

Install DejaVu fonts

tar -xf dejavu-fonts-ttf-2.37.tar.bz2
cp dejavu-fonts-ttf-2.37/ttf/*.ttf ~/Library/Fonts/
rm -rf dejavu-fonts-ttf-2.37/ dejavu-fonts-ttf-2.37.tar.bz2

iTerm2 theming

Download iTerm2-Color-Schemes and unpack it. Import the unpacked schemes folder it into iTerm Preferences/Profiles/Colors settings. Try different themes or have a look at for a gallery. I prefer the theme Solarized Dark Higher Contrast, which is based on Solarized.
You can get the original Solarized theme at

Restore function keys

  • Apple Menu -> System Preferences -> Keyboard
  • Tick "Use All F1, F2, etc keys as standard function keys"


* VIM replaced by neovim

* Visual Studio Code added

* Commander One added
* HandBrake added
* VeraCrypt instructions updated


  • MacDown exchanged with haroopad
  • fish shell instructions updated
  • VeraCrypt / OSXFUSE instructions updated

Common mistakes in software licensing systems

Leaving debug information in the binaries

The default compiler settings leave more information in the binary than you want someone to have. Especially for Mac compiled binaries, the amount of contained information is dangerous. Try to inspect your compiled binary with a hexeditor or load it into the free version of IDA Pro and scroll through it. It is not uncommon that a text search for serial or license will show the name and address of the internal function that may be visibly named 'bool IsLicensed()'.

Leaving a key generator in the binary

A common mistake is to leave a key generator function in the binary. A user enters a name and Serial and tries to register your product. The mistake is now to use an internal function that takes the name as a parameter and returns a valid serial like 'String GetSerial(String name)'. To check if the entered serial is valid, a simple string comparison is done now. A cracker may be able to rip that valid serial returning function and put it into a keygenerator.

Having one attack point

If you have an internal function like 'bool IsLicensed()', all a cracker needs to do is find and identify this function and change the code to always return true. This can be done by just patching 3 byte in your binary. If there is only one point in your code that does call this function, a cracker can crack your program by patching just the conditional jump after the IsLicensed call to jump without any condition, this is a 1 byte patch.

Giving immediate feedback on a registration try

While it might seem a good idea at first to give the user an immediate feedback on the product registration, it's also the point of attack for every cracker. "Your serial is invalid" is a typical example. It's better to ask the user for a program restart and do the serial check somewhere in the program initialization.

Using text references

If you want to show that your program is Unregistered, try to not use text but an image resource to do so. The first thing a cracker does after loading your product in a Disassembler, is looking for text references for typical words like: license, registered, serial, trial

Not obfuscating Java or .Net bytecode

The standard bytecode of a compiled Java or .Net compile contains all class, function and variable names that you used in your source code. Using a bytecode obfuscator like Proguard for Android will get rid of this by renaming all classes to a,b,c,... The functionality of your program is still given.

Relying only on a commercial software licensing product to secure your app

This may save you time implementing your own solution and prevent some of the listed mistakes, your used commercial software like Armadillo is also a very attractive target for the cracking community. Usually the teams will built their own tools to defeat such software in a generic way in seconds. At the end, this may end in the fastest of all ways to crack your software.

Blacklisting of serials

While this might seem a good idea at first, it can do more harm than good. A cracker that did not posses a valid serial before is given now one for free. All he need to do is change one byte of the blacklisted serial in the binary to make this serial work again.

Hidden menu entries or parameter to generate a valid serial or license

Security by obscurity is a bad idea in that case. A cracker will find it and abuse it.

Finding a Travel Laptop

I wanted to get a cheap notebook that i can use while travelling. My requirements were the following:

  • Possibility to run Linux or Windows 8.1 (not RT)
  • Minimum 4 GB RAM
  • SSD of at least 128 GB
  • Dual Core x86 CPU
  • Enough power for 720p x264 video playback
  • Maximum weight 1,5 kg

The ACER Aspire V3-371-57S2 (600 Eu) or Microsoft Surface 3 (870 Eu) matched that requirements, but with a price of 600 Euro it was more than I wanted to spend. I decided to get and older Chromebook that had the possibility to upgrade the RAM and hard drive. For a list of Chromebooks and their upgradeability, look at archlinux Chromebook listing. The Acer C710 was one of the very few Chromebooks that allowed to replace the internal hard disk and RAM. There are two models of the C710, the difference is the CPU of 1.1 GHz Intel Celeron 847 vs the faster 1.5 GHz Intel Celeron 1007U. I got the following items on ebay:

Item Price
Acer Chromebook C7 C710-10072G01ii 135 EU
Elpida 8GB DDR3 SODIMM 45 EU
Crucial BX100 250GB SATA 6Gb/s 2.5" Internal SSD 85 EU

Replacing the hardware can be done in a short amount of time following the instruction of ifixit. Instructions on how to install Ubuntu can be found at For the overall price of 265 Euro I got a device with the following specifications:

Item Specs
Screen 11.6" 1366x768 16:9
CPU Intel Celeron 1007U, 1,5GHz
SSD 250 GB
Ports VGA, HDMI, Ethernet, SD slot, 3x USB
OS Ubuntu 14.04 / Chrome OS Dual-boot
Weight 1,4 kg

After using the device for a while, I noticed a few downsides:

  • The current Ubuntu has some issues, the system settings (unity-control-center) crash when trying to open it ("Gen6+ requires Kernel 3.6 or later.") and system error messages pop up frequently ("System program problem detected")
  • The battery load jumps suddenly from 15% to 5% with just enough time left to save everything and shut down the device
  • The trackpad misbehaves, the reason for this seems to be a hardware grunding issues, as explained on reddit. A fix for this can be found at

How to detect if your Windows application is running under Wine

In 2005, Microsoft started the anti-piracy initiative called Genuine Advantage. To be able to download from Microsoft Download Center, you would have had to pass the validation. It was the first time that Microsoft acknowledged the existence of Wine, by blocking its access to the downloads if a Wine specific registry key was found by the ActiveX control or their standalone tool.

These are some ways to detect Wine:


Check for the existence of "SOFTWARE\Wine\Wine\Config"

Presence of Wine specific API exports

wine_get_version in ntdll.dll (

Running processes

On a normal Windows system there will always be some specific processes running like csrss.exe (Client/Server Runtime Subsystem), dwm.exe (Desktop Window Manager), explorer.exe (File Explorer) and winlogon.exe (Winlogon). Some of those exes are just present in a specific range of Windows versions, so you have to consider those when checking for their presence. Not having them present could also mean that your application is running on a newer Windows that does not use them anymore. A normal Windows should generally speaking have more then 10 processes running, even if you don't have any programs running and under a non administrator account that does not allow you to view the list of running system processes. Having not much processes could as well mean that your program is running inside a sandbox.

Missing API functions or functionality

When you search for "unsupported" in the Wine source you will find easily places that have been identified to miss functionality to behave exactly like Windows. The file dlls\ntdll\om.c contains the API NtQueryObject and by looking at the code it sesms like it is missing support for some values in the main switch. This API is not officially documented by Microsoft but...

API code

The API entry code generated by gcc will be different than the one that Microsoft Visual Studio compiler generates.

API files

The Wine dll files are compiled different than the native Windows ones, there is another number of PE sections in files like kernel32.dll

Creating small executables with Microsoft Visual Studio

Starting with an empty project, I will show you how to use Microsoft Visual Studio 2010 to compile your C code without the usual bloating that the compiler adds automatically. This article will just feature C code, I may extend this blog entry for usage with C++ at a later point.

In the empty workspace, create a new file called tinyexe.c with following content:

#include <windows.h>

void main()
  MessageBoxA(0, "Hello", "world!", MB_OK);

Switch the solution configuration from Debug to Release and compile the project (F7 is the default key for this). The output will be a 6.656 byte sized exe file. Could have been worse I would say 🙂 Let's have a look at what is inside the exe, I am using the file view of Total Commander which will give you a nice view of the file content and showing zero bytes as whitespace.

This is the portable executable header, containing 5 section definitions (.text, .rdata, .data, .rsrc, .reloc).

The code section contains way more code than needed for calling the 2 Windows APIs in our code.

This section contains the import table, import address table as well as a reference to a .pdb debug info file. In the list of imported API functions you will see way more APIs than the 2 that we actually intended to use. The reference to mscvrt.dll means that this exe uses functions of the Microsoft Visual C Run-Time Library, which we did not intend to do. The Visual Studio compiler adds the crt library initialization code by default which then calls our main function.

At the end of this exe file you can see a manifest xml file followed by relocation data, both features we do not need.

Lets see how we can pimp that exe (without using external tools) now:

  • To get rid of the console window that pops up on program start set the project option Linker/System/Subsystem to Windows (/SUBSYSTEM:WINDOWS)
  • Set the project option Linker/Advanced/Entry Point to main. This will remove the crt library initialization code and since we don't use any C standard library functions also the reference to the msvcrt dll.
  • Set Linker/Debugging/Generate Debug Info to No. This will remove the .pdb debug information file reference.
  • Set Linker/Manifest File/Generate Manifest to No. Now the manifest xml is removed.
  • Set Linker/Advanced/Randomized Base Address to No. We don't need relocations for a normal non library project.

Compile the project again and the resulting exe file will now be 2.048 byte small and look like this:

Between the DOS stub and PE header you can find the undocumented Rich Signature from Microsoft, which is present in newer Visual Studio compiler versions and is not needed, so you could zero those bytes out.

Back To Top