Skip to content

Instantly share code, notes, and snippets.

@jdmedeiros
Created September 3, 2025 20:38
Show Gist options
  • Save jdmedeiros/0c6fefa4c4d632add0521f786da89513 to your computer and use it in GitHub Desktop.
Save jdmedeiros/0c6fefa4c4d632add0521f786da89513 to your computer and use it in GitHub Desktop.
// Build: gcc -O0 -fno-pie -no-pie totp.c -o totp -lcrypto
// Notes:
// -O0 keeps simple branches
// -fno-pie -no-pie makes addresses stable & easy to map to file offsets
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <inttypes.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#define ONE_WEEK_IN_SECONDS 604800
static const char *ASCII_LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
__attribute__((section(".data"))) unsigned char reveal = 0xAA;
static uint32_t hotp_sha1(const uint8_t *key, size_t key_len, uint64_t counter) {
uint8_t msg[8];
for (int i = 7; i >= 0; --i) { msg[i] = (uint8_t)(counter & 0xFF); counter >>= 8; }
unsigned int hlen = 0;
unsigned char hmac[EVP_MAX_MD_SIZE];
if (!HMAC(EVP_sha1(), key, (int)key_len, msg, sizeof msg, hmac, &hlen) || hlen != 20) {
fprintf(stderr, "HMAC failed\n");
return 0;
}
int offset = hmac[19] & 0x0F;
uint32_t bin_code =
((uint32_t)(hmac[offset] & 0x7F) << 24) |
((uint32_t)(hmac[offset+1] & 0xFF) << 16) |
((uint32_t)(hmac[offset+2] & 0xFF) << 8 ) |
((uint32_t)(hmac[offset+3] & 0xFF));
return bin_code;
}
int main(void) {
time_t now = time(NULL);
if (now == (time_t)-1) { perror("time"); return 1; }
uint64_t counter = (uint64_t)now / ONE_WEEK_IN_SECONDS;
uint32_t totp = hotp_sha1((const uint8_t*)ASCII_LETTERS, strlen(ASCII_LETTERS), counter) % 100000000U;
if (reveal == 0xAB) {
printf("%08" PRIu32 "-%ld\n", totp, (long)now);
} else {
printf("Tell the secret? Nope, I am not a snitch!\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment