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

Gh0st配置加密与解密算法(异或、Base64)的更多相关文章

  1. DES的加密与解密算法(Python实现)

    DES的加密与解密算法(Python实现) 密码学实验:实现了DES的简单的加密和解密算法,DES算法的相关资料网上很多,这里不再赘述,仅仅贴出源代码给大家分享,源码中包含很多汉字注释,相信大家都是可 ...

  2. JAVA实现AES的加密和解密算法

    原文 JAVA实现AES的加密和解密算法 import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import ja ...

  3. 常见的加密和解密算法—AES

    一.AES加密概述 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用 ...

  4. 常见的加密和解密算法—DES

    一.DES加密概述 DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并 ...

  5. 常见的加密和解密算法—BASE64

    一.BASE64加密和解密概述 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64编码可用于在HTTP环境下传递较长的标识信息.例如,在Java Persistence系 ...

  6. 常见的加密和解密算法—MD5

    一.MD5加密概述 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 13 ...

  7. BASE64,MD5,SHA,HMAC加密與解密算法(java)

    package com.ice.webos.util.security; import java.io.UnsupportedEncodingException; import java.math.B ...

  8. java之--加密、解密算法

    0.概述 在项目开发中,我们常需要用到加解密算法,加解密算法主要分为三大类: 1.对称加密算法,如:AES.DES.3DES 2.非对称加密算法,如:RSA.DSA.ECC 3.散列算法,如:MD5. ...

  9. c# DESEncrypt 加密、解密算法

    using System; using System.Security.Cryptography; using System.Text; namespace AttendService { publi ...

随机推荐

  1. Nginx - request_time和upstream_response_time的区别

    request_time 官网描述:request processing time in seconds with a milliseconds resolution; time elapsed be ...

  2. P4433 [COCI2009-2010#1] ALADIN

    题目描述 给你 n 个盒子,有 q 个操作,操作有两种: 第一种操作输入格式为"1 L R A B",表示将编号为L到R的盒子里的石头数量变为(X−L+1)×A mod B,其中 ...

  3. C++11并发编程个人小结

    thread_local变量在每个线程第一次执行到时初始化(类似static),并在每个线程各自累加,并在线程结束时释放. std::condition_variable:: wait(std::un ...

  4. 使用msiexec.exe绕过应用程序白名单(多种方法)

    0x00 前言 在我们之前的文章中,我们讨论了“Windows Applocker策略 - 初学者指南”,因为它们为应用程序控制策略定义了AppLocker规则,以及如何使用它们.但今天您将学习如何绕 ...

  5. 一次绕过防火墙获取RCE以及提权到root权限的渗透过程

    本文是关于Apache struts2 CVE-2013-2251是由于导致执行远程命令的影响而被高度利用的漏洞.简而言之, 通过操纵以“action:”/”redirect:”/”redirectA ...

  6. 项目管理---git----遇到问题------.gitignore不起作用

    情况 在管理一个版本库时,有时候不想要管理某些文件,这个时候我就把这个问价写到.gitignore文件中,这样应该就可以将这个文件忽略,不再进行·版本管理了,但是经常出现的情况是:将这些文件名写到其中 ...

  7. Java中的三目运算符可能出现的问题

    你真的了解Java中的三目运算符吗? 原创 2018-04-27 刨根问底的 Hollis Hollis Hollis 微信号 hollischuang 功能介绍 一个对Coding有着独特追求的人. ...

  8. codeforces contest 1111

    A. Superhero Transformation 题意: 元音和元音,辅音和辅音字母之间可以互相转换,问两个字符串是否想同: 题解:直接判断即可: #include<bits/stdc++ ...

  9. python对MySQL的CRUD

    我是闲的没事干,2014过的太浮夸了,博客也没写几篇,哎~~~ 用这篇来记录即将逝去的2014 python对各种数据库的各种操作满大街都是,不过,我还是喜欢我这种风格的,涉及到其它操作,不过重点还是 ...

  10. Docker集群管理Swarm数据持久化

    一.前言 和docker容器一样,Swarm集群中运行的服务也能够做数据持久化.我们可以通过volume.bind和nfs等方式来实现swarm集群应用数据的持久化.其实和docker数据持久化的形式 ...