101

Re: Низькорівнева всячина

Ну макроси це для свого коду. А у сторонніх файлах, відрізнити код і дані, як? Висер компілятора ще можна зрозуміти, бо там усе статично по дефолту, а якщо маніяк типу вас, зробить динамічний розрахунок вказівників на дані, і таку операцію розіпре на 100 інструкцій, то що робити?

Подякували: leofun011

102

Re: Низькорівнева всячина

Значить маніяк типу мене має зазначити вручну де код а де дані, але найбільшу небезпеку я бачу в недокументованих інструкціях та Небесній Брамі, тому для таких речей потрібна пісочниця а не голий емулятор. Все ж я агітую вас працювати над повним технологічним циклом, на рейки якого можливо швидко перевести старі проєкти і криптувати тоді сторонні файли не доведеться. Обкатувати частину технологій та вчити потрібні засоби розробки/документування можливо на осдеві та (ретро)ґеймдеві.

103

Re: Низькорівнева всячина

Розповідає Роман Лещенко, власник фірми «Агродар» (Черкаська обл., в обробітку 3 000 га):

«На одному нашому зернозбиральному комбайні умільці перепрошили електронний модуль, що відповідав за врожайність соняшнику. Він показував, що ми збираємо 24 ц/га, хоча реальна врожайність була десь 28 ц/га».

Різницю місцеві хакери крали й продавали у своєму ж районі, на цьому і погоріли.

Звідсіля

Сільські кіберпанки боряться з всеохопною владою агрокорпорацій, які за безцінь скупили землю через належність їхніх власників до партноменклатури.

Подякували: reverse2500, leofun01, 221VOLT3

104 Востаннє редагувалося Kane 2.0 (07.04.2018 19:44:37)

Re: Низькорівнева всячина

Розрахунок crc32 для файлів.

#include <windows.h>

typedef DWORD (__stdcall *_RtlComputeCrc32)(DWORD, const BYTE*, INT);

#define CRC32_BLOCK_SIZE 1024


DWORD get_crc32_of_file(LPCSTR sFileName)
{
    _RtlComputeCrc32 RtlComputeCrc32 = (_RtlComputeCrc32)GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlComputeCrc32");

    HANDLE hFile = CreateFileA(sFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hFile != INVALID_HANDLE_VALUE) {
        BYTE aBuf[CRC32_BLOCK_SIZE];
        DWORD dwCrc32 = 0, dwBytesRead;

        while (ReadFile(hFile, aBuf, CRC32_BLOCK_SIZE, &dwBytesRead, NULL) && dwBytesRead != 0) {
            dwCrc32 = RtlComputeCrc32(dwCrc32, aBuf, dwBytesRead);
        }

        CloseHandle(hFile);

        return dwCrc32;
    }

    return -1;
}


void entry()
{
    char *aFiles[] = {"test_1.txt", "test_2.txt", "test_3.txt"};

    for (size_t i = 0; i < sizeof(aFiles) / sizeof(aFiles[0]); i++) {
        char aBuf[MAX_PATH + 20];
        wsprintfA(aBuf, "%s = %08X", aFiles[i], get_crc32_of_file(aFiles[i]));
        OutputDebugStringA(aBuf);
    }

    ExitProcess(0);
}

105 Востаннє редагувалося Kane 2.0 (07.04.2018 19:43:48)

Re: Низькорівнева всячина

Був розмістив на факаві, та як мені стало зрозуміло, подібне там мало хто по суті може оцінити. Взагалі, форум із скріпткідді.
І так, Hex dump. Підтримує паддинг, встановлення ширини слова/загальної ширини, колонку ASCII (0x20 - 0x7F та 0xC0 - 0xFF).

0012FE40 | 00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F | ................ |
0012FE50 | 10 11 12 13  14 15 16 17  18 19 1A 1B  1C 1D 1E 1F | ................ |
0012FE60 | 20 21 22 23  24 25 26 27  28 29 2A 2B  2C 2D 2E 2F |  !"#$%&'()*+,-./ |
0012FE70 | 30 31 32 33  34 35 36 37  38 39 3A 3B  3C 3D 3E 3F | 0123456789:;<=>? |
0012FE80 | 40 41 42 43  44 45 46 47  48 49 4A 4B  4C 4D 4E 4F | @ABCDEFGHIJKLMNO |
0012FE90 | 50 51 52 53  54 55 56 57  58 59 5A 5B  5C 5D 5E 5F | PQRSTUVWXYZ[\]^_ |
0012FEA0 | 60 61 62 63  64 65 66 67  68 69 6A 6B  6C 6D 6E 6F | `abcdefghijklmno |
0012FEB0 | 70 71 72 73  74 75 76 77  78 79 7A 7B  7C 7D 7E 7F | pqrstuvwxyz{|}~  |
0012FEC0 | 80 81 82 83  84 85 86 87  88 89 8A 8B  8C 8D 8E 8F | ................ |
0012FED0 | 90 91 92 93  94 95 96 97  98 99 9A 9B  9C 9D 9E 9F | ................ |
0012FEE0 | A0 A1 A2 A3  A4 A5 A6 A7  A8 A9 AA AB  AC AD AE AF | ................ |
0012FEF0 | B0 B1 B2 B3  B4 B5 B6 B7  B8 B9 BA BB  BC BD BE BF | ................ |
0012FF00 | C0 C1 C2 C3  C4 C5 C6 C7  C8 C9 CA CB  CC CD CE CF | АБВГДЕЖЗИЙКЛМНОП |
0012FF10 | D0 D1 D2 D3  D4 D5 D6 D7  D8 D9 DA DB  DC DD DE DF | РСТУФХЦЧШЩЪЫЬЭЮЯ |
0012FF20 | E0 E1 E2 E3  E4 E5 E6 E7  E8 E9 EA EB  EC ED EE EF | абвгдежзийклмноп |
0012FF30 | F0 F1 F2 F3  F4 F5 F6 F7  F8 F9 FA FB  FC FD FE FF | рстуфхцчшщъыьэюя |

Ф-я:

typedef enum _word_size {
    WORD_4_BYTE = 4,
    WORD_8_BYTE = 8
} word_size;

typedef enum _dump_width {
    WIDTH_4 = 4,
    WIDTH_8 = 8,
    WIDTH_16 = 16,
    WIDTH_32 = 32
} dump_width;


#define c_r(n, a, b) (((n) >= (a)) && ((n) <= (b)))

/*
    word:   размер слова (WORD_4_BYTE, WORD_8_BYTE)
    width:  ширина дампа в байтах (WIDTH_4, WIDTH_8, WIDTH_16, WIDTH_32)
    no_col: true - сплошные байты, false - разделять по размеру слова
    buf:    буфер
    num:    размер буфера
*/
void hex_dump(const word_size word, const dump_width width, bool no_col, void *const buf, const size_t num)
{
    if (width >= word && !(width % word) && c_r(width, WIDTH_4, WIDTH_32) && buf && num > 0) {
        const uint32_t pad = width - ((num - 1) % width) + num - 1;

        for (size_t i = 0; i < pad; i++) {
            if (!(i % width))
                printf("%08X | ", (uint32_t)buf + i);

            if (i < num)
                printf("%02X", ((uint8_t *)buf)[i]);
            else
                printf("--");

            printf((i + 1) % (width / (no_col ? 1 : width / word)) ? " " : ((i + 1) % width ? "  " : " | "));

            if (!((i + 1) % width) || i + 1 == pad) {
                for (size_t j = i + 1 - width; j < i + 1 ? true : (printf(" |\n"), false); j++) {
                    if (j < num) {
                        uint8_t c = ((uint8_t *)buf)[j];
                        putchar(c_r(c, 0x20, 0x7F) || c_r(c, 0xC0, 0xFF) ? c : '.');
                    } else {
                        putchar('.');
                    }
                }
            }
        }

        putchar('\n');
    } else {
        printf("hex_dump error!\n");
        exit(1);
    }
}

Код..

    char *s = "test string, тестовая сТрОкА, 1234567890";
    hex_dump(WORD_4_BYTE, WIDTH_16, false, s, strlen(s) + sizeof((char)'\n'));

..покаже наступним чином:

00409000 | 74 65 73 74  20 73 74 72  69 6E 67 2C  20 F2 E5 F1 | test string, тес |
00409010 | F2 EE E2 E0  FF 20 F1 D2  F0 CE EA C0  2C 20 31 32 | товая сТрОкА, 12 |
00409020 | 33 34 35 36  37 38 39 30  00 -- -- --  -- -- -- -- | 34567890........ |

106 Востаннє редагувалося Kane 2.0 (07.04.2018 19:43:42)

Re: Низькорівнева всячина

Рекурсивний пошук файлів. Виконує рекурсивний пошук по розширенню і назві файлу на зовнішніх/зйомних/мережевих носіях, використовує єдиний буфер. Також містить можливість виключення директорій для пошуку (windows/program files та ін.). В якості критики, було зазначено, що бажано використовувати unicode-шляхи замість зазначених тут ascii (MAX_PATH).

#include <windows.h>
#include <Shlwapi.h>

#include <stdio.h>
#include <stdbool.h>


// ---------------------------------------------------------------------------------------

// папки в которых исключено сканирование
static const char *dir[] = {
    "windows",
    "program files",
    "program files (x86)",
    "system volume information"
};

// файлы для поиска
static const char *fil[] = {
    "Visual Studio 2015.lnk",
    "Sublime Text 3.lnk",
    "start.bat",
    "Программируем Raspberry Pi на голом железе _ Хабрахабр.htm"
};

// расширения, по которым нужно искать
static const char *ext[] = {
    ".rar",
    ".zip",
    ".mp3",
    ""          // файлы без расширения
};

// ---------------------------------------------------------------------------------------

typedef enum _dir_fil_ext {
    E_DIR = 0,
    E_FIL,
    E_EXT
} dir_fil_ext;

#define arr_sz(a) (sizeof(a) / sizeof(a[0]))

bool check(char *dst, dir_fil_ext dfe)
{
    const char **src;
    size_t n;

    switch (dfe) {
        case E_DIR:
            src = dir;
            n = arr_sz(dir);
            break;

        case E_FIL:
            src = fil;
            n = arr_sz(fil);
            break;

        case E_EXT:
            src = ext;
            n = arr_sz(ext);
            break;
    }

    for (size_t i = 0; i < n; i++)
        if (/*!lstrcmpiA(dst, src[i])*/ CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, dst, -1, src[i], -1) == CSTR_EQUAL)
            return true;

    return false;
}

// ---------------------------------------------------------------------------------------

void get_file(char *szPath)
{
    WIN32_FIND_DATAA sWin32FindData;

    int iPath = lstrlenA(szPath);
    lstrcatA(szPath, "*.*");

    HANDLE hFindFile = FindFirstFileA(szPath, &sWin32FindData);

    if (hFindFile != INVALID_HANDLE_VALUE) {
        do {
            if (!lstrcmpA(sWin32FindData.cFileName, ".") || !lstrcmpA(sWin32FindData.cFileName, ".."))
                continue;

            szPath[iPath] = '\0';
            lstrcatA(szPath, sWin32FindData.cFileName);

            if (sWin32FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                if (!check(sWin32FindData.cFileName, E_DIR)) {
                    lstrcatA(szPath, "\\");
                    get_file(szPath);
                }
            } else {
                if (check(sWin32FindData.cFileName, E_FIL) || check(PathFindExtensionA(sWin32FindData.cFileName), E_EXT)) {
                    printf("%s\n", szPath);
                }
            }
        } while (FindNextFileA(hFindFile, &sWin32FindData));

        FindClose(hFindFile);
    }
}

void get_drive()
{
    DWORD dwDrives = GetLogicalDrives();

    for (char szPath[MAX_PATH + 1] = "A:\\"; dwDrives; dwDrives >>= 1, szPath[0]++) {
        if (dwDrives & 1) {
            UINT dwType = GetDriveTypeA(szPath);

            if (dwType == DRIVE_REMOVABLE || dwType == DRIVE_FIXED || dwType == DRIVE_REMOTE) {
                get_file(szPath);
                szPath[3] = '\0';

                putchar('\n');
            }
        }
    }
}


int main(void)
{
    get_drive();

    return 0;
}
Подякували: 0xDADA11C7, leofun012

107 Востаннє редагувалося Kane 2.0 (07.04.2018 19:43:54)

Re: Низькорівнева всячина

Генератор сміттєвих іконок.

Переглядаючи семпли різної малварі, іноді доводиться бачити файли з абсолютно нехитрою іконкою - піксельний рандом з прозорими областями. Таке часто використовується у файлах призначених для прогрузу, просто й ефектно. На черговому файлі, захотілося подібне реалізувати, що і було зроблено. Заодно стала зрозумілою структура * .ico.
Отже:

icogen.h

#ifndef ICOGEN_H
#define ICOGEN_H

#include <windows.h>

#define SystemFunction036 NTAPI SystemFunction036
#include <NTSecAPI.h>
#undef SystemFunction036

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


typedef struct _ICONDIRENTRY {
    BYTE bWidth;
    BYTE bHeight;
    BYTE bColorCount;
    BYTE bReserved;
    WORD wPlanes;
    WORD wBitCount;
    DWORD dwBytesInRes;
    DWORD dwImageOffset;
} ICONDIRENTRY, *PICONDIRENTRY;

typedef struct _ICONDIR {
    WORD idReserved;
    WORD idType;
    WORD idCount;
    PICONDIRENTRY idEntries;
} ICONDIR, *PICONDIR;

typedef struct _ICONIMAGE {
    BITMAPINFOHEADER icHeader;
    RGBQUAD *icColors;
    BYTE *icMask;
} ICONIMAGE, *PICONIMAGE;


typedef struct _ICON {
    FILE *hFile;
    ICONDIR IconDir;
    PICONIMAGE pIconImage;
} ICON, *PICON;


/*
    szFileName - файл иконки
    aIcoSize - массив с требуемыми размерами иконок (min - 1x1, max - 256x256)
    uIcoCount - кол-во элементов (иконок) в массиве
    uIcoColor - кол-во используемых цветов
    bTransp - прозрачность (от 0 до 255)

    return: 0 - успех; -1 - ошибка
*/
int WINAPI icogen_create_ico(const char *szFileName, const uint32_t aIcoSize[], const size_t uIcoCount, const uint32_t uIcoColor, const uint8_t bTransp);

#endif

icogen.c

#include "icogen.h"

ULONG icogen_rnd(const uint32_t uMin, const uint32_t uMax)
{
    ULONG lRnd;

    return RtlGenRandom(&lRnd, sizeof(ULONG)) ? (uMin <= uMax ? lRnd % (uMax - uMin + 1) + uMin : -1) : -1;
}


int icogen_size_is_ok(const uint32_t aIcoSize[], const size_t uIcoCount) {
    for (size_t i = 0; i < uIcoCount; i++) {
        if (aIcoSize[i] < 1 || aIcoSize[i] > 256)
            return -1;
    }

    return 0;
}


#define get_mask_size(bit) (((bit)+31)/32*4*(bit))


PICON icogen_init(const char *szFileName, const uint32_t aIcoSize[], const size_t uIcoCount, const uint32_t uIcoColor)
{
    if (!icogen_size_is_ok(aIcoSize, uIcoCount) && uIcoCount >= 1 && uIcoColor >= 1) {
        PICON pIcon = NULL;

        if (pIcon = calloc(1, sizeof(ICON))) {
            if (pIcon->hFile = fopen(szFileName, "wb")) {
                if (pIcon->IconDir.idEntries = calloc(uIcoCount, sizeof(ICONDIRENTRY))) {
                    if (pIcon->pIconImage = calloc(uIcoCount, sizeof(ICONIMAGE))) {
                        for (size_t i = 0; i < uIcoCount; i++) {
                            if (!(pIcon->pIconImage[i].icColors = calloc(aIcoSize[i] * aIcoSize[i], sizeof(RGBQUAD))))
                                return NULL;

                            if (!(pIcon->pIconImage[i].icMask = calloc(1, get_mask_size(aIcoSize[i]))))
                                return NULL;
                        }

                        return pIcon;
                    }
                }
            }
        }
    }

    return NULL;
}


void icogen_clear(PICON pIcon, const size_t uIcoCount)
{
    for (size_t i = 0; i < uIcoCount; i++) {
        if (pIcon->pIconImage[i].icMask)
            free(pIcon->pIconImage[i].icMask);

        if (pIcon->pIconImage[i].icColors)
            free(pIcon->pIconImage[i].icColors);
    }

    if (pIcon->pIconImage)
        free(pIcon->pIconImage);

    if (pIcon->IconDir.idEntries)
        free(pIcon->IconDir.idEntries);

    fclose(pIcon->hFile);

    if (pIcon)
        free(pIcon);
}


void icogen_write(PICON pIcon, const uint32_t aIcoSize[], const size_t uIcoCount)
{
    // icondir
    fwrite(&pIcon->IconDir.idReserved, sizeof(pIcon->IconDir.idReserved), 1, pIcon->hFile);
    fwrite(&pIcon->IconDir.idType, sizeof(pIcon->IconDir.idType), 1, pIcon->hFile);
    fwrite(&pIcon->IconDir.idCount, sizeof(pIcon->IconDir.idCount), 1, pIcon->hFile);

    fwrite(pIcon->IconDir.idEntries, sizeof(ICONDIRENTRY), uIcoCount, pIcon->hFile);

    for (size_t i = 0; i < uIcoCount; i++) {
        // header
        fwrite(&pIcon->pIconImage[i].icHeader, sizeof(pIcon->pIconImage[i].icHeader), 1, pIcon->hFile);

        // rgb
        fwrite(pIcon->pIconImage[i].icColors, sizeof(RGBQUAD), aIcoSize[i] * aIcoSize[i], pIcon->hFile);

        // mask
        fwrite(pIcon->pIconImage[i].icMask, get_mask_size(aIcoSize[i]), 1, pIcon->hFile);
    }
}


int WINAPI icogen_create_ico(const char *szFileName, const uint32_t aIcoSize[], const size_t uIcoCount, const uint32_t uIcoColor, const uint8_t bTransp)
{
    PICON pIcon = NULL;

    if (pIcon = icogen_init(szFileName, aIcoSize, uIcoCount, uIcoColor)) {
        DWORD dwImageOffsetPrev = uIcoCount * sizeof(ICONDIRENTRY) + sizeof(WORD) * 3;

        pIcon->IconDir.idReserved = 0;
        pIcon->IconDir.idType = 1;
        pIcon->IconDir.idCount = (WORD)uIcoCount;

        for (size_t i = 0; i < uIcoCount; i++) {
            pIcon->IconDir.idEntries[i].bWidth = aIcoSize[i];
            pIcon->IconDir.idEntries[i].bHeight = aIcoSize[i];
            pIcon->IconDir.idEntries[i].bColorCount = 0;
            pIcon->IconDir.idEntries[i].bReserved = 0;
            pIcon->IconDir.idEntries[i].wPlanes = 1;
            pIcon->IconDir.idEntries[i].wBitCount = 32;
            pIcon->IconDir.idEntries[i].dwBytesInRes = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * aIcoSize[i] * aIcoSize[i]) + get_mask_size(aIcoSize[i]);
            pIcon->IconDir.idEntries[i].dwImageOffset = dwImageOffsetPrev;

            pIcon->pIconImage[i].icHeader.biSize = sizeof(BITMAPINFOHEADER);
            pIcon->pIconImage[i].icHeader.biWidth = aIcoSize[i];
            pIcon->pIconImage[i].icHeader.biHeight = 2 * aIcoSize[i];
            pIcon->pIconImage[i].icHeader.biPlanes = 1;
            pIcon->pIconImage[i].icHeader.biBitCount = 32;
            pIcon->pIconImage[i].icHeader.biCompression = 0;
            pIcon->pIconImage[i].icHeader.biSizeImage = 0;
            pIcon->pIconImage[i].icHeader.biXPelsPerMeter = 0;
            pIcon->pIconImage[i].icHeader.biYPelsPerMeter = 0;
            pIcon->pIconImage[i].icHeader.biClrUsed = 0;
            pIcon->pIconImage[i].icHeader.biClrImportant = 0;

            RGBQUAD *rgb = calloc(uIcoColor, sizeof(RGBQUAD));
            memset(rgb, bTransp, uIcoColor * sizeof(RGBQUAD));

            uint32_t jmp = 0;

            for (size_t j = 0; j < aIcoSize[i] * aIcoSize[i]; j++) {
                if (!(j % (aIcoSize[i] * aIcoSize[i] / icogen_rnd(1, aIcoSize[i])))) {
                    for (size_t k = 0; k < uIcoColor; k++) {
                        RtlGenRandom(rgb + k, 3);
                    }

                    jmp = jmp ? 0 : 1;
                }

                if (icogen_rnd(jmp, 1)) {
                    pIcon->pIconImage[i].icColors[j] = rgb[icogen_rnd(0, uIcoColor - 1)];
                }
            }

            if (rgb)
                free(rgb);

            RtlGenRandom(pIcon->pIconImage[i].icMask, get_mask_size(aIcoSize[i]));

            dwImageOffsetPrev += pIcon->IconDir.idEntries[i].dwBytesInRes;
        }

        icogen_write(pIcon, aIcoSize, uIcoCount);
        icogen_clear(pIcon, uIcoCount);

        return 0;
    }

    return -1;
}

main.c

#include "icogen.h"

int main(int argc, char **argv)
{
    const uint32_t ico[] = { 16, 24, 32, 48, 128, 256 };

    if (!icogen_create_ico("icon.ico", ico, sizeof(ico) / sizeof(ico[0]), 2, 255)) {
        printf("Successfully completed!\n");
    } else {
        printf("Error!\n");
    }

    return 0;
}

Використання на fasm:

    format pe console 5.01


    section '.text' import readable executable

    include 'win32a.inc'

    library icogen_dll, 'icogen_dll.dll',\
            kernel32, 'kernel32.dll',\
            msvcrt, 'msvcrt.dll'


    import  icogen_dll,\
            icogen_create_ico, 'icogen_create_ico'

    import  kernel32,\
            ExitProcess, 'ExitProcess'

    import  msvcrt,\
            printf, 'printf'


entry $

    invoke icogen_create_ico, fname, ico, ico_sz, 2, 255
    test eax, eax
    jne .e
    cinvoke printf, s
    jmp .s
.e: cinvoke printf, e
.s: invoke ExitProcess, 0


    ico         dd 16, 24, 32, 48, 128, 256
    ico_sz      = ($ - ico) / 4

    fname       db 'icon.ico', 0

    s           db 'Successfully completed!', 13, 10, 0
    e           db 'Error!', 13, 10, 0

на Python:

#!/usr/bin/env py -3

import ctypes
import struct

icogen_dll = ctypes.windll.LoadLibrary('icogen_dll.dll')

sz = 16, 24, 32, 48, 128, 256

if not icogen_dll.icogen_create_ico(b'icon.ico', struct.pack(str(len(sz)) + 'I', *sz), len(sz), 2, 255):
    print("Successfully completed!\n")
else:
    print("Error!\n")
Подякували: 0xDADA11C7, leofun012

108 Востаннє редагувалося Kane 2.0 (07.04.2018 19:43:58)

Re: Низькорівнева всячина

І ще, питаннячко до пізнавших дзен системщини: чи етично хачити софт СНГ-виробника і кидати до пабліку?

109

Re: Низькорівнева всячина

Вважаю, що етично. Вам оте СНГ треба чи що? Звичайно, що є нормальні люди, але... Швидше повиздихає - леше дихатиметься.

Подякували: leofun011

110

Re: Низькорівнева всячина

Як правило хакають і викладають в паблік аби полоскотати своє самолюбство.

111

Re: Низькорівнева всячина

Як правило посрадянські "хакери" є недобаригами, тому не аргумент. Самолюбство в цьому випадку найкраща риса цих вумних кулхацкерів. Дрючба (навколо)хакерських цехів невідворотна! Втім, як і університетів з "універстиетами" та байкерів(Пекельні Ангели) з "байкерами"(Нічні Вовки).

112 Востаннє редагувалося Kane 2.0 (07.04.2018 19:43:27)

Re: Низькорівнева всячина

Буває ще на фоні якоїсь неприязні (конкуренція), або ж софт відверте лайно. Тим паче це рушій прогресу для автора і він скоріше оновить програму ...або закриється)

Прихований текст

Ну й просто гарний привід про себе заявити спільноті.. чи ні? Да усі "привати", того ж вищевказаного факаву, на половину заповнені подібними похеками ті іншими "утєчкамі" :D
Чергова двояка ситуація. В наших реаліях і сучасному розумінні публічного "андеграунду" - більше шкоди вийде, аніж добра та репутації.

113

Re: Низькорівнева всячина

Дискусія з Олегом Фаренюком вконтакті (веде блог http://indrekis2.blogspot.com/):
Petro Dadaistenko
дякую, я планую криптографію на брейнхваці написати для криптора/протектора, щоби антивірусники сказилися.
17 бер в 0:25

Олег Фаренюк
Petro, Ви з Infected Voice не стикалися? :=) Згадалося, як Light General Forth-о подібну мову для того юзав.
А щодо сказилися... Я тут викладаю С++ — так половина популярних антивірусів банальний "Hello world" оголошують вірусом і грохають, різко ускладнюючи життя зовсім початківцям.
17 бер в 0:33 Petro

Petro Dadaistenko
Олег, стикався і навіть балакав з LovinGod`ом 5 год тому. Стекова машина не питання — я сам маю такий реліз (http://replace.org.ua/topic/4076/ криптор, окрема стекова машина http://replace.org.ua/topic/3262/ з прикладом генерації послідовності Фобоначчі, написаний стороннім кодером) і авери майже сказилися — детектили мене по коду передачі параметрів у стекову ВМ.
17 бер в 0:41 Олеговi

Олег Фаренюк
Petro, о, і що Маестро хорошого каже? :=)

Згадуючи Light General, про нього нічого не чули? Із всієї тієї компашки мені його труди якось все найближчими були :=)

Щодо криптора і відповідної віртуальної машини — шикарно! І взагалі цікаво, а українською просто б не очікував чогось такого побачити :=) На жаль, вникати поки не маю ресурсів, але отримав масу задоволення, проглядаючи!

До речі, згадавши дивака, який на Ардуїно ЛІнукс запустив (емулятор АРМ зробивши і підключивши RAM від 286-го), отак сходу, а якщо написати для віртуальної машини емулятор іншої, і вже для неї код буде щось цікаве робити, можна припустити, що б АВ-и подумади?

П.С. "Все цікаве має сенс" — ППКС! Задовбався повторювати, не вірять. :=)
17 бер о 10:09 Petro|Відповісти

Олег Фаренюк
Petro, до речі, Brainfuck згадуючи і пару моїх (сподіваюся — поки) не завершених наукових досліджень, із Befungi Ви стикалися? :=)
17 бер о 10:10 Petro

Petro Dadaistenko
Олег, я посварив LG з його другом через FASM. Я не дуже заглиблювався у IV, мені там ближчі віршики, а ВМ уживаються у комерційних протекторах - теміді, наприклад.
> а якщо написати для віртуальної машини емулятор іншої, і вже для неї код буде щось цікаве робити, можна припустити, що б АВ-и подумади?
Питання стоїть в тому, щоби широко варіювати архітектуру ВМ та її реалізацію. Мені вдалося ціною неймовірних зусиль всунути в 715 байт ВМ, якби те саме переписати високорівневою мовою чи додати серйозний морхвинг, то не менш ніж на 3 кілобайти потягне, а це - найпростіша RISC-ова ВМ. А оскільки машинний код ВМ генерується рандомним кодом, то 715 байт перетворюється на 3 кілобайти, а 3 кілобайтна ВМ перетвориться на 15 кілобайтний код, яку вже за довжиною процедури генерації нескладно задетектити статично. А от якби створити меншу ВМ, яку б можна було морхвити в широкому діапазоні, то авери сказились би. А ще я міркую над багатошаровою криптографією, тоді б можна було додати і подвійну віртуалізацію.
17 бер о 13:30 Олеговi

Олег Фаренюк
Petro, Навіть не знаю, що сказати :=)))) А щодо IV — для мене тоді це було одне із дуже небагатьох джерел інформації про "низький рівень", другим був Пітер Абель, третім - пісдлухані розмови. :=) От, про Forth взнав, наприклад, обробку переривань, завантаження MZ-EXE, і т.д.. (Мова про 1995-1999 роки, див. http://indrekis2.blogspot.com/2013/02/dos-fcb.html )

Для чого використовується така технологія, звичайно, знаю :=) У мене, крім природного в 16 років, інтересу до вірусів, цілком практична зацікавленість в поліморфних техніках — ряд незавершених наукових досліджень такого плану: https://en.wikipedia.org/wiki/Tierra_(computer_simula.. . Якщо зовсім коротко, такий підхід, при всій фантастичності перших результатів і відомої (з інших робіт) можливості самозародження "організмів"-реплікаторів, так виглядає, все ж обмежений — вище певного рівня складність віртуальних організмів не росте. Маю ряд варіантів спробувати подолати ці обмеження. 1. Багатомірність (тому й befungi згадався), 2. локальність — робити, щоб доступ до сусідніх адрес ВМ був простішим, ніж до далеких, 3. робити самі ВМ реплікаторами — не знаємо поки, котрі із них важливіші, і всі можна обгрунтувати.
Так-так, питання із розміром я зразу виключив із поля уваги — зрозуміло, що при віртуалці у віртуалці він різко (чи не експоненційно?) росте. Стало цікаво, може у Вас сходу є якісь міркування щодо реакції евристики та емуляторів АВ на таку рекурсивність — чисто в межах "художественного трепа". :=)

Щодо постановки задачі, так, дійшло :=)
17 бер о 14:37 Petro

Олег Фаренюк
Petro, до речі, FASM, Light General-а та віруси згадуючи: https://сайт-злодій/note8447776_9143326 :=)
17 бер о 14:49 Petro

Petro Dadaistenko
Олег,
>Стало цікаво, може у Вас сходу є якісь міркування щодо реакції евристики та емуляторів АВ на таку рекурсивність — чисто в межах "художественного трепа". :=)

Емулятори мають глибину емуляції, на моїй стековій машині воно видихалося, щоправда великі файли довго розпаковувалися навіть на справжній машині.
> вище певного рівня складність віртуальних організмів не росте.
гадаю це через однорідність середовища. Тому що б не робилося - виросте "Янукович" - примітивне та ехвективне :) Я думаю написати криптора і спробувати застосувати на ньому машиннне навчання, але це дуже далекі плани.
вчора о 1:38 Олеговi

Олег Фаренюк
Petro, та я теж на нелокальність грішу — сенсу розвиватися, як до кожного байту в одномірному "бульйоні" дотягнутися можна :=)

Машинне навчання - штука специфічна, неоднозначна... Хоча, буває, цікаво виходить. В рамках братової дисертації запускали нейромережі на мікроконтролерах, правда, швидше як Technology demo, але поки буде захист, сподіваюся, і більш практичне доросте. :=)
вчора о 20:23 Petro

114

Re: Низькорівнева всячина

Сидю, читаю джерельні коди дуже коштовного продукту, до речі, повністю FASM`ом писаного, і бачу:

        inifile,'\Alghazanth - A Living Grave.mp3',\
        idsfile,'\Alghazanth - Only The Reflections Bleeds.mp3',\
Alghazanth - A Living Grave
Alghazanth - Only The Reflections Bleeds

115

Re: Низькорівнева всячина

На дамазі я вже постив, нехай і тут побуде. Алго rc4.

; ------------------------------------
proc rc4, k, kn, d, dn
; k - ключ
; kn - розмір ключа
; d - буфер
; dn - розмір буфера
; ------------------------------------
    locals
        s rb 256
        v dd 256
    endl

    lea edi, [s]
    mov esi, edi

    xor ecx, ecx
    xor eax, eax
@@: stosb
    inc eax
    cmp eax, [v]
    jne @b

    xor edi, edi
@@: mov bl, byte[esi + ecx]
    add edi, ebx

    mov eax, ecx
    xor edx, edx
    mov ebx, [kn]
    div ebx

    mov eax, [k]
    mov bl, byte[eax + edx]
    add edi, ebx

    mov eax, edi
    mov ebx, [v]
    div ebx

    mov edi, edx

    mov bl, [esi + ecx]
    xchg [esi + edi], bl
    mov [esi + ecx], bl

    inc ecx
    cmp ecx, [v]
    jne @b

    xor ecx, ecx
    xor eax, eax
    xor edi, edi

@@: push eax
    inc ecx
    mov eax, ecx
    xor edx, edx
    mov ebx, [v]
    div ebx
    mov ecx, edx

    mov bl, byte[esi + ecx]
    add edi, ebx
    
    mov eax, edi
    mov ebx, [v]
    div ebx
    mov edi, edx

    mov bl, [esi + ecx]
    xchg [esi + edi], bl
    mov [esi + ecx], bl

    mov al, byte[esi + ecx]
    add al, byte[esi + edi]
    mov ebx, [v]
    div ebx

    mov bl, byte[esi + edx]

    pop eax
    add eax, [d]
    xor [eax], bl
    sub eax, [d]

    inc eax
    cmp eax, [dn]
    jne @b

    ret
endp

116

Re: Низькорівнева всячина

Багато з тих хто пізнав дзен програмування на plain C, полюбляв писати "хакерський код". За приклад опишемо у подібному стилі crc32

uint32_t crc32(char *b, size_t n)
{
    uint32_t c = ~0, i = ~c;

    while (n-- ? c ^= *b++ : i)
        while (i++ < 8 ? c = (c >> 1) ^ (c % 2 * 0xEDB88320) : (i = 0));

    return ~c;
}

малозрозуміле жлобство :) Нажаль ця стислість, якщо робити оптимізацію за розміром, оманлива. Вищевказаний код займає 88 байт (pelles c).

перепишемо по нормальному (зрозуміліше для людського сприйняття)

uint32_t crc32(char *b, size_t n)
{
    uint32_t c = ~0;

    for (size_t i = 0; i < n; ++i, ++b) {
        c ^= *b;

        for (size_t j = 0; j < 8; ++j)
            c = (c >> 1) ^ (c % 2 * 0xEDB88320);
    }

    return ~c;
}

тут ми маємо 67 байт. Зекономлено цілий 21 байт! Як ми бачимо, стислість коду на C не означає малий розмір машинного коду.

Звісно це не стосується більш інтелектуальних братів типу clang-cl та intel c.

117

Re: Низькорівнева всячина

Іще, щодо розрахування розміру кода функцій на C. Дуже зручно використовувати макроси

#define start(f) __declspec(naked) void start_##f(void) {};
#define end(f) __declspec(naked) void end_##f(void) {};
#define calc_size(f) (uint8_t*)end_##f - (uint8_t*)start_##f

приклад

start(func)
uint32_t func(...)
{
    ...
}
end(func)

printf("size: %d\n", calc_size(func));

118

Re: Низькорівнева всячина

А цей компактний ніштяк із мого старого проекту, аналог GetProcAddress, який шукає по crc32-хешу від імені api, замість самого ASCIIZ-імені.

__declspec(naked) DWORD __stdcall get_addr(HMODULE hMod, DWORD dwApi)
{
    __asm {
        mov ebx, [esp + 4]

        mov esi, dword[ebx + 0x3C]                  ; IMAGE_DOS_HEADER.e_lfanew
        mov esi, dword[esi + ebx + 0x78]            ; IMAGE_DOS_HEADER.e_lfanew shl 1
        add esi, ebx

        xor edi, edi
        jmp _start

    _b: mov eax, dword[esi + 0x20]                  ; IMAGE_EXPORT_DIRECTORY.AddressOfNames
        add eax, ebx
        mov eax, dword[edi * 4 + eax]
        add eax, ebx

        ; strlen
        mov ecx, eax
    _len:
        cmp byte[ecx], 1
        inc ecx
        jae _len
        sbb ecx, eax

        ; crc32
        mov edx, eax
        jecxz _null_len

        sub eax, eax
        dec eax

    _next_byte:
        xor al, byte[edx]
        mov bl, 8
        
    _bc:
        shr eax, 1
        jnc _chet
        xor eax, 0EDB88320h
    _chet:
        dec bl
        jne _bc

        inc edx
        loop _next_byte
        
        not eax
    _null_len:
        cmp eax, [esp + 8]
        je _fin

        inc edi

    _start:
        cmp edi, dword[esi + 0x18]                   ; IMAGE_EXPORT_DIRECTORY.NumberOfNames
        jb _b
        sub eax, eax
        dec eax
        jmp _err

    _fin:
        mov eax, dword[esi + 0x24]                   ; IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
        add eax, ebx

        movzx edi, word[edi * 2 + eax]

        mov esi, dword[esi + 0x1C]                   ; IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
        add esi, ebx
        mov eax, dword[edi * 4 + esi]
        add eax, ebx

    _err:
        ret 8
    }
}

На вхід подаємо хендл dll, та хеш.

get_addr(LoadLibraryA("user32.dll"), 0x572D5D8E);  //0x572D5D8E - MessageBoxA

119

Re: Низькорівнева всячина

малозрозуміле жлобство :) Нажаль ця стислість, якщо робити оптимізацію за розміром, оманлива. Вищевказаний код займає 88 байт (pelles c).

Я пишу щось середнє - обожнюю тернарний оператор та уникаю вживання конструкції if, якщо він спричиняє лише одну дію. Приклад

fUnicode || pBuffer++;

Pelles C не найкращій компілер з точки зору продукованого ним коду (особливо в звичайному режимі), проте зручний в використанні своїм мінімалізмом та сумісністю з Visual C++

120

Re: Низькорівнева всячина

0xDADA11C7 написав:

та уникаю вживання конструкції if

так, теж спосіб до пари із "," та "?:". Правда негарно виходить із void-функціями, бо там треба приводити до int

void func(void)
{
    ...
}

if (1)
    func();
=>
1 && ((int(*)(void))func)();

і треба завжди коментувати, бо через пару місяців фіг зрозумієш що воно таке))

У мене з pelles c складності виникали коли я на ньому писав PI-код. Надмірна самостійність проявлялася при увімкненій оптимізації, і подібні хаки разом із delta-приставками компілятор просто не розумів, та коцав код. До глобальних масивів, дельту він додає вже після(O_o) використання, тому потрібно було робити додаткові __asm-милиці. Підкупає своєю простотою та невибагливістю.

Ну і ще трохи всячини - циклічний зсув, якого нам так не вистачає.

uint32_t rol(uint32_t v, uint32_t n)
{
    return n %= (sizeof(v) * 8), (v << n) | (v >> (sizeof(v) * 8 - n));
}

uint32_t ror(uint32_t v, uint32_t n)
{
    return n %= (sizeof(v) * 8), (v >> n) | (v << (sizeof(v) * 8 - n));
}
Подякували: 0xDADA11C71