Skip to content

Instantly share code, notes, and snippets.

@fador
Last active September 13, 2022 17:33
Show Gist options
  • Save fador/138bc8b18e7c532e039f28ca57908b69 to your computer and use it in GitHub Desktop.
Save fador/138bc8b18e7c532e039f28ca57908b69 to your computer and use it in GitHub Desktop.
Paste TOTP directly to the console with a hotkey in windows
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctime>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <string>
#include <windows.h>
#include <shobjidl.h>
#include <objbase.h>
#include <sal.h>
#include <stdarg.h>
#include <wchar.h>
#include <thread>
#pragma comment(lib, "ws2_32.lib")
#pragma comment (lib, "crypt32")
const char* base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
// Modified from https://github.com/arachsys/totp
std::string generate_totp() {
int64_t offset;
size_t keysize, length;
uint8_t digits, * hmac, key[64], msg[8];
uint32_t bits, code, count;
uint64_t clock, interval;
unsigned int hmacsize;
const EVP_MD* digest;
keysize = 0;
char out[100];
const char* secret = "TOTP_SECRET_KEY ";
digest = EVP_sha1();
for (count = bits = length = 0; *secret; secret++) {
if (!strchr(base32, *secret))
break;
bits = (bits << 5) | (strchr(base32, *secret) - base32);
count += 5;
while (count >= 8) {
while (length >= keysize) {
keysize = keysize ? keysize << 1 : 64;
if (keysize>64)
return "";
}
count -= 8, key[length++] = bits >> count;
}
}
offset = 0;
if (length > 0) {
clock = (time(NULL) - offset) / 30;
for (count = 0; count < 8; count++)
msg[7 - count] = clock >> 8 * count;
hmac = HMAC(digest, key, length, msg, sizeof(msg), NULL, &hmacsize);
for (code = count = 0; count < 4; count++)
code += hmac[(hmac[hmacsize - 1] & 0x0f) + 3 - count] << 8 * count;
code &= 0x7fffffff;
sprintf_s(out,"%06u", code % 1000000);
}
out[6] = '\0'; // Force null byte to end the 6 digits
std::string output(out);
return output;
}
bool KeyPress(UINT key)
{
INPUT inputs[2];
ZeroMemory(inputs, sizeof(inputs));
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = key;
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = key;
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
return true;
}
bool send_otp() {
std::string totp = generate_totp();
INPUT inputs[2];
ZeroMemory(inputs, sizeof(inputs));
// CTRL up before the input
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_LCONTROL;
inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wScan = ::MapVirtualKey(LOBYTE(VkKeyScan('1')), MAPVK_VK_TO_VSC);
inputs[1].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
UINT uSent = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
for (char key : totp) {
if (key >= '0' && key <= '9') { // Force only numbers
//const SHORT Vk = VkKeyScan(key);
//const UINT VKey = ::MapVirtualKey(LOBYTE(Vk), MAPVK_VK_TO_VSC);
KeyPress((key-'0') + 0x30); // Map ASCII to Windows virtual keys
Sleep(2);
}
}
return true;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
if (RegisterHotKey(NULL, 1, MOD_CONTROL, 0x31)) // CTRL+1
{
// Done
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_HOTKEY)
{
send_otp();
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment