【算法】Gh0st配置加密算法(异或、Base64)

1、前言

分析木马程序常常遇到很多配置信息被加密的情况,虽然现在都不直接分析而是通过Wireshark之类的直接读记录。

2017年Gh0st样本大量新增,通过对木马源码的分析还发现有利用Gh0st加密方式来传播的源码中的后门。

2、加密思路

  • 控制端:对字符串异或、移位、Base64编码
  • 服务端:对字符串Base64解码、移位、异或

3、实践代码

  • 加密编码
// Base64编码
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int C模仿Gh0st加密上线地址Dlg::base64_encode(const void *data, int size, char **str)
{
    char *s, *p;
    int i;
    int c;
    const unsigned char *q;

    p = s = (char*)malloc(size * 4 / 3 + 4);
    if (p == NULL)
        return -1;
    q = (const unsigned char*)data;
    i = 0;
    for (i = 0; i < size;) {
        c = q[i++];
        c *= 256;
        if (i < size)
            c += q[i];
        i++;
        c *= 256;
        if (i < size)
            c += q[i];
        i++;
        p[0] = base64[(c & 0x00fc0000) >> 18];  //base64
        p[1] = base64[(c & 0x0003f000) >> 12];
        p[2] = base64[(c & 0x00000fc0) >> 6];
        p[3] = base64[(c & 0x0000003f) >> 0];
        if (i > size)
            p[3] = ‘=‘;
        if (i > size + 1)
            p[2] = ‘=‘;
        p += 4;
    }
    *p = 0;
    *str = s;
    return strlen(s);
}

// 加密函数
char * C模仿Gh0st加密上线地址Dlg::MyEncode(char *str)
{
    int     i, len;
    char    *s, *data;
    // 字符串长度
    len = strlen(str) + 1;
    // 开辟字符串相对应的内存空间
    s = (char *)malloc(len);
    // 将字符串拷贝到开辟出来的指针中
    memcpy(s, str, len);
    // 异或操作
    for (i = 0; i < len; i++)
    {
        s[i] ^= 0x19;
        s[i] += 0x86;
    }
    // Base64编码
    base64_encode(s, len, &data);
    free(s);

    return data;
}
  • 解密编码
// Base64密钥
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 解码密钥
int C模仿Gh0st加密上线地址Dlg::pos(char c)
{
    char *p;
    for (p = base64; *p; p++)
        if (*p == c)
            return p - base64;
    return -1;
}

// Base64解码
int C模仿Gh0st加密上线地址Dlg::base64_decode(const char *str, char **data)
{
    const char *s, *p;
    unsigned char *q;
    int c;
    int x;
    int done = 0;
    int len;
    s = (const char *)malloc(strlen(str));
    q = (unsigned char *)s;
    for (p = str; *p && !done; p += 4) {
        x = pos(p[0]);
        if (x >= 0)
            c = x;
        else {
            done = 3;
            break;
        }
        c *= 64;

        x = pos(p[1]);
        if (x >= 0)
            c += x;
        else
            return -1;
        c *= 64;

        if (p[2] == ‘=‘)
            done++;
        else {
            x = pos(p[2]);
            if (x >= 0)
                c += x;
            else
                return -1;
        }
        c *= 64;

        if (p[3] == ‘=‘)
            done++;
        else {
            if (done)
                return -1;
            x = pos(p[3]);
            if (x >= 0)
                c += x;
            else
                return -1;
        }
        if (done < 3)
            *q++ = (c & 0x00ff0000) >> 16;

        if (done < 2)
            *q++ = (c & 0x0000ff00) >> 8;
        if (done < 1)
            *q++ = (c & 0x000000ff) >> 0;
    }

    len = q - (unsigned char*)(s);

    *data = (char*)realloc((void *)s, len);

    return len;
}

// 解密函数
char* C模仿Gh0st加密上线地址Dlg::MyDecode(char *str)
{
    int     i, len;
    char    *data = NULL;
    len = base64_decode(str, &data);

    for (i = 0; i < len; i++)
    {
        data[i] -= 0x86;
        data[i] ^= 0x19;
    }
    return data;
}

然后就是加密解密界面的内容。

函数代码:

  • 生成配置信息按钮
void C模仿Gh0st加密上线地址Dlg::OnBnBuild()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
    m_remote_host.Replace(L" ", L"");
    m_remote_port.Replace(L" ", L"");

    CString str = m_remote_host + ":" + m_remote_port;
    str.MakeLower();
    TCHAR * pWStrKey;         // 合并后的内容

    // 开辟数组
    pWStrKey = new TCHAR[str.GetLength() + 1];
    pWStrKey = str.GetBuffer(0);

    // 第一次 调用确认转换后单字节字符串的长度,用于开辟空间
    int pSize = WideCharToMultiByte(CP_OEMCP, 0, pWStrKey, wcslen(pWStrKey), NULL, 0, NULL, NULL);
    // 单字符
    char* pCStrKey = new char[pSize + 1];
    // 第二次 调用将双字节字符串转换成单字节字符串
    WideCharToMultiByte(CP_OEMCP, 0, pWStrKey, wcslen(pWStrKey), pCStrKey, pSize, NULL, NULL);
    pCStrKey[pSize] = ‘\0‘;

    // 接收char*
    m_encode = MyEncode(pCStrKey);

    m_encode.Insert(0, L"AAAA");
    m_encode += "AAAA";

    UpdateData(FALSE);
}
  • 解密配置信息按钮

void C模仿Gh0st加密上线地址Dlg::OnBnGetLoginInfo()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);

    // 1 获取加密编辑控件里的字符串
    int pSize = m_encode.GetLength() + 1;
    wchar_t * pStart, *pEnd;
    wchar_t strKey[] = L"AAAA";
    wchar_t strEncode[1024];

    // 拿到最开始的字符串,如果前面是AAAA就赋值到pStart
    pStart = wcsstr(m_encode.GetBuffer(0), strKey);
    // 前移动4个字节,也就是跳过AAAA
    pStart += 4;
    // 如果AAAA匹配不到把strKey,也就是AAAA赋值给pEnd
    pEnd = wcsstr(pStart, strKey);
    // 清空原先AAAA字符串
    wmemset(strEncode, 0, wcslen(pStart) + 1);
    // 取key值之间的内容,配置字符串 - 字符串长度,取前面的真实加密字符串
    wmemcpy(strEncode, pStart, pEnd - pStart);
    // 单字符
    char* pCStrKey = new char[wcslen(strEncode) + 1];
    // 调用将双字节字符串转换成单字节字符串
    WideCharToMultiByte(CP_OEMCP, 0, strEncode, wcslen(strEncode) + 1, pCStrKey, wcslen(strEncode) + 1, NULL, NULL);
    pCStrKey[pSize] = ‘\0‘;

    // 解密代码
    m_decode = MyDecode(pCStrKey);

    UpdateData(FALSE);
}

4、实际效果

5、参考

gh0st3.6源码分析(1)——木马的生成

http://blog.csdn.net/hjxyshell/article/details/19094609

原文地址:https://www.cnblogs.com/17bdw/p/8483413.html

时间: 2024-10-12 12:12:11

【算法】Gh0st配置加密算法(异或、Base64)的相关文章

java单向加密算法小结(1)--Base64算法

java单向加密算法小结(1)--Base64算法 从这一篇起整理一下常见的加密算法以及在java中使用的demo,首先从最简单的开始. 简单了解 Base64严格来说并不是一种加密算法,而是一种编码/解码的实现方式. 我们都知道,数据在计算机网络之间是使用字节流的方式进行传递的,所有的信息都要最终转换为0101的二进制,这本身就涉及到编码,解码的应用. Base64,顾名思义,是使用了64个基本的字符来对任意数据进行编码的一种实现方式,那既然有Base64,是不是也有Base32,Base16

.ssh/config 文件的解释算法及配置原则

前言 SSH 是连接远程主机最常用的方式,尽管连接到耽搁主机的基本操作非常直接,但当你开始使用大量的远程系统时,这就会成为笨重和复杂的任务. 幸运的是,OpenSSH 允许您提供自定义的客户端连接选项.这些选项可以被存储到一个配置文件中,这个配置文件可以用来定义每个主机的配置.这有助于保持每个主机的连接选项更好的独立和组织,也你让你在需要连接时避免在命令行中写繁琐的选项. 在本文中,我们将介绍 SSH 客户端配置文件的基本知识,了解 SSH 如何解释配置文件,但不会介绍 SSH 具体选项的含义及

java算法----------常用的加密算法

散列算法(单向散列,不可逆) MD5(Message Digest Algorithm 5) SHA(Secure Hash Algorithm)   对称加密(加密解密使用同一密钥,速度快) DES 3DES AES 非对称加密(公钥加密,私钥解密,可以签名,更安全) RSA ECC 原文地址:https://www.cnblogs.com/hanxue112253/p/9574144.html

python 加密算法sha和base64

# coding=utf-8import base64from hashlib import sha1 sha= sha1()sha.update(b"aaa"+b"bbb") # 字符串相加等价于两次update# sha.update(b'bbb')aa=sha.hexdigest() str=aa.encode('utf-8')bs64=base64.b64encode(str)print(bs64) #b'NjhkODU3MmMyNjYyYjBmMDZmNz

Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

[前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及用法和样例 [最简单的加密] 1.简单的概念 明文:加密前的信息 密文:机密后的信息 算法:加密或解密的算法 密钥:算法使用的钥匙(读作miyao.正确应该是miyue,可是大家都读miyao) 2.简单的样例 将123456每位数字都加1后得到234567, 当中123456就是明文.234567就是密文.加密密钥就是1,加密算法是每位加 3.对称加密和非对称加密 以上为例. 123456-->234567的加密

Base64算法

一. Base64算法概述 Base64算法最早应用于解决电子邮件传输的问题.早期,由于“历史问题”,电子邮件只允许ASCII码字符,如果邮件中包含非ASCII码字符,当它通过有“历史问题”的网关时,这个网关会对该字符的二进制位进行调整,即将其8位二进制码的最高位置0,这样用户收到的邮件就会是一封乱码.为了解决这个问题,产生了Base64算法. Base64主要用于将不可打印的字符转换成可打印字符,或者简单的说将二进制数据编码成ASCII字符(注:可打印的). 将二进制数据编码成ASCII字符主

Android数据加密之Base64编码算法

前言: 前面学习总结了平时开发中遇见的各种数据加密方式,最终都会对加密后的二进制数据进行Base64编码,起到一种二次加密的效果,其实呢Base64从严格意义上来说的话不是一种加密算法,而是一种编码算法,为何要使用Base64编码呢?它解决了什么问题?这也是本文探讨的东西?下面是其他数据加密链接地址: Android数据加密之Rsa加密 Android数据加密之Aes加密 Android数据加密之Des加密 Android数据加密之MD5加密 什么Base64算法? Base64是网络上最常见的

base64随机字符混淆加密、解密-美拍视频地址解密,反推加密算法

用火车头测试采集美拍的数据时无意中发现美拍的视频地址是一段加了混淆字符串的base64代码.如下图 于是好奇之下研究了下解密算法.具体过程省略800字.发现美拍的视频解密是通过js完成,于是找到了具体的解密代码,如下: 1 ;(function(a) { 2 var b = "substring", 3 c = "split", 4 d = "replace", 5 e = "substr", 6 f = { 7 getHex

[转]加密算法(DES,AES,RSA,MD5,SHA1,Base64)比较和项目应用

原文链接:http://www.cnblogs.com/sochishun/p/7028056.html 加密技术通常分为两大类:"对称式"和"非对称式". 对称性加密算法:对称式加密就是加密和解密使用同一个密钥.信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行加解密了.对称加密算法用来对敏感数据等信息进行加密. 非对称算法:非对称式加密就是加密和解密所使用的不是同一个密钥,通常有两个密钥,称为"公钥"和"私