create it
покачто не умеет открывать зависимости других библиотек
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.a
|
||||
*.o
|
||||
*.dll
|
||||
*.kex
|
||||
23
.vscode/c_cpp_properties.json
vendored
Normal file
23
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/include",
|
||||
"/home/autobuild/tools/win32/include",
|
||||
"/home/autobuild/tools/win32/lib/gcc/mingw32/5.4.0/include",
|
||||
"${workspaceFolder}/../kolibrios/contrib/C_Layer/INCLUDE"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/home/autobuild/tools/win32/bin/kos32-gcc",
|
||||
"compilerArgs": [
|
||||
"-nostdinc -fno-builtin -fno-ident -fomit-frame-pointer -DMISSING_SYSCALL_NAMES -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -std=c11"
|
||||
],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++11",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
32
.vscode/settings.json
vendored
Normal file
32
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"editor.insertSpaces": false,
|
||||
"cSpell.words": [
|
||||
"dlfcn",
|
||||
"dlloader",
|
||||
"dlopen",
|
||||
"ksys"
|
||||
],
|
||||
"files.associations": {
|
||||
"ksys.h": "c",
|
||||
"cstdio": "cpp",
|
||||
"exception": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"new": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"array": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"string": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"istream": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"cmath": "cpp",
|
||||
"kolibri_libini.h": "c",
|
||||
"dlfcn.h": "c",
|
||||
"list": "c",
|
||||
"format": "c",
|
||||
"thread": "c"
|
||||
}
|
||||
}
|
||||
82
Makefile
Normal file
82
Makefile
Normal file
@@ -0,0 +1,82 @@
|
||||
NAME=dlopen
|
||||
|
||||
CC=kos32-gcc
|
||||
LD=kos32-ld
|
||||
STRIP=kos32-strip
|
||||
OBJCOPY=kos32-objcopy
|
||||
|
||||
|
||||
MYCFLAGS =
|
||||
MYLDFLAGS =
|
||||
DEBUG_INFO=0
|
||||
|
||||
CFLAGS= -O2 -Wall -Iinclude -std=c11 -DDEBUG_INFO=$(DEBUG_INFO) $(MYCFLAGS) $(SYSCFLAGS)
|
||||
AR= kos32-ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
LIBS= $(MYLIBS) $(SYSLIBS)
|
||||
|
||||
|
||||
STATIC_NAME=$(NAME).a
|
||||
|
||||
DLL_NAME=$(NAME).dll
|
||||
DLL_IMPL=$(DLL_NAME).a
|
||||
|
||||
ALL_A= $(STATIC_NAME)
|
||||
ALL_DLL=$(DLL_NAME) $(DLL_IMPL)
|
||||
|
||||
ALL_TESTS= test.kex
|
||||
|
||||
ALL_BIN=$(ALL_A) $(ALL_DLL) $(ALL_TESTS)
|
||||
|
||||
|
||||
#########
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
TOOLCHAIN_PATH=C:/MinGW/msys/1.0/home/autobuild/tools/win32
|
||||
else
|
||||
TOOLCHAIN_PATH=/home/autobuild/tools/win32
|
||||
endif
|
||||
|
||||
SYSCFLAGS= -nostdinc -fno-builtin -fno-ident -fomit-frame-pointer \
|
||||
-U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 \
|
||||
-I$(TOOLCHAIN_PATH)/lib/gcc/mingw32/5.4.0/include -I$(TOOLCHAIN_PATH)/lib/gcc/mingw32/5.4.0/include-fixed -I$(TOOLCHAIN_PATH)/include
|
||||
SYSLDFLAGS=--image-base 0 -Tapp-dynamic.lds
|
||||
SYSLIBS=-nostdlib -L$(TOOLCHAIN_PATH)/mingw32/lib -lgcc -lc.dll -ldll
|
||||
|
||||
#########
|
||||
|
||||
OBJECTS = src/dlopen.o src/loader.o src/sha256.o
|
||||
#../kolibrios/contrib/C_Layer/OBJ/loadlibini.obj
|
||||
|
||||
default: $(ALL_BIN)
|
||||
|
||||
|
||||
|
||||
$(STATIC_NAME): $(OBJECTS)
|
||||
$(AR) $@ $?
|
||||
|
||||
$(DLL_NAME): $(OBJECTS)
|
||||
$(LD) -shared -T dll.lds --entry _DllStartup -o $@ $^ --out-implib $(DLL_IMPL) $(LIBS)
|
||||
|
||||
$(DLL_IMPL): $(DLL_NAME)
|
||||
|
||||
|
||||
test.kex: tests/test.o dlopen.a
|
||||
$(LD) -o $@ $(SYSLDFLAGS) $(MYLDFLAGS) $^ $(LIBS)
|
||||
$(STRIP) -S $@
|
||||
$(OBJCOPY) $@ -O binary
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(ALL_BIN)
|
||||
|
||||
# deps
|
||||
|
||||
tests/test.o: tests/test.c include/dlfcn.h src/loader.h
|
||||
|
||||
src/dlopen.o: src/dlopen.c include/dlfcn.h
|
||||
src/loader.o: src/loader.c src/loader.h src/sha256.h
|
||||
src/loader.h: src/pe.h
|
||||
src/sha256.o: src/sha256.c src/sha256.h
|
||||
|
||||
5
README.md
Normal file
5
README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# DLopen for kolibriOS
|
||||
|
||||
Умеет загружать `dll` и `obj`, расшаривать `dll`.
|
||||
|
||||
Загрузчик `PE` основан на том, что в newlib. Использует [Функцию 68, подфункцию 22](https://git.kolibrios.org/KolibriOS/kolibrios/src/commit/c17d1a57a313968946d166ac25d8a0d117f85a94/kernel/trunk/docs/sysfuncr.txt#L3497) для расшаривания
|
||||
78
include/dlfcn.h
Normal file
78
include/dlfcn.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef _DLFCN_H
|
||||
#define _DLFCN_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum DLOPEN_FLAGS
|
||||
{
|
||||
/*
|
||||
Perform lazy binding. Resolve symbols only as the code
|
||||
that references them is executed. If the symbol is never
|
||||
referenced, then it is never resolved. (Lazy binding is
|
||||
performed only for function references; references to
|
||||
variables are always immediately bound when the shared
|
||||
object is loaded.).
|
||||
*/
|
||||
RTLD_LAZY,
|
||||
|
||||
/*
|
||||
If this value is specified, or the environment variable
|
||||
LD_BIND_NOW is set to a nonempty string, all undefined
|
||||
symbols in the shared object are resolved before dlopen()
|
||||
returns. If this cannot be done, an error is returned.
|
||||
|
||||
Zero or more of the following values may also be ORed in flags:
|
||||
*/
|
||||
RTLD_NOW,
|
||||
|
||||
/*
|
||||
The symbols defined by this shared object will be made
|
||||
available for symbol resolution of subsequently loaded
|
||||
shared objects.
|
||||
*/
|
||||
RTLD_GLOBAL,
|
||||
|
||||
/*
|
||||
This is the converse of RTLD_GLOBAL, and the default if
|
||||
neither flag is specified. Symbols defined in this shared
|
||||
object are not made available to resolve references in
|
||||
subsequently loaded shared objects.
|
||||
*/
|
||||
RTLD_LOCAL,
|
||||
|
||||
/*
|
||||
Do not unload the shared object during dlclose().
|
||||
Consequently, the object's static and global variables are
|
||||
not reinitialized if the object is reloaded with dlopen()
|
||||
at a later time.
|
||||
*/
|
||||
RTLD_NODELETE,
|
||||
|
||||
/*
|
||||
Don't load the shared object. This can be used to test if
|
||||
the object is already resident (dlopen() returns NULL if it
|
||||
is not, or the object's handle if it is resident). This
|
||||
flag can also be used to promote the flags on a shared
|
||||
object that is already loaded. For example, a shared
|
||||
object that was previously loaded with RTLD_LOCAL can be
|
||||
reopened with RTLD_NOLOAD | RTLD_GLOBAL.
|
||||
*/
|
||||
RTLD_NOLOAD,
|
||||
|
||||
/*
|
||||
Place the lookup scope of the symbols in this shared object
|
||||
ahead of the global scope. This means that a self-
|
||||
contained object will use its own symbols in preference to
|
||||
global symbols with the same name contained in objects that
|
||||
have already been loaded.
|
||||
*/
|
||||
RTLD_DEEPBIND
|
||||
};
|
||||
|
||||
void *dlopen(const char *filename, int flag);
|
||||
const char *dlerror(void);
|
||||
void *dlsym(void *handle, char *symbol);
|
||||
int dlclose(void *handle);
|
||||
|
||||
|
||||
#endif // _DLFCN_H
|
||||
85
src/dlopen.c
Normal file
85
src/dlopen.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <dlfcn.h>
|
||||
#include <sys/ksys.h>
|
||||
#include <string.h>
|
||||
#include "loader.h"
|
||||
|
||||
enum TYPE
|
||||
{
|
||||
OBJ,
|
||||
DLL
|
||||
};
|
||||
|
||||
struct dll
|
||||
{
|
||||
enum TYPE t;
|
||||
uint8_t flags;
|
||||
void *h;
|
||||
};
|
||||
|
||||
void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
struct dll *dll = _ksys_alloc(sizeof(dll));
|
||||
dll->flags = flag;
|
||||
|
||||
char *e = strrchr(filename, '.') + 1;
|
||||
if (strcmp(e, "dll") == 0)
|
||||
{
|
||||
printf("load dll: %s\n", filename);
|
||||
dll->t = DLL;
|
||||
dll->h = load_PE_dll(filename);
|
||||
}
|
||||
else if (strcmp(e, "obj") == 0)
|
||||
{
|
||||
printf("load obj: %s\n", filename);
|
||||
dll->t = OBJ;
|
||||
dll->h = _ksys_dlopen(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ksys_free(dll);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dll;
|
||||
}
|
||||
|
||||
const char *dlerror(void)
|
||||
{
|
||||
return dll_err;
|
||||
}
|
||||
|
||||
void *dlsym(void *handle, char *symbol)
|
||||
{
|
||||
void *f = NULL;
|
||||
switch (((struct dll *)handle)->t)
|
||||
{
|
||||
case DLL:
|
||||
f = get_pe_proc(((struct dll *)handle)->h, symbol);
|
||||
break;
|
||||
case OBJ:
|
||||
f = _ksys_dlsym(((struct dll *)handle)->h, symbol);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int dlclose(void *handle)
|
||||
{
|
||||
if (((struct dll *)handle)->flags == RTLD_NODELETE)
|
||||
{
|
||||
switch (((struct dll *)handle)->t)
|
||||
{
|
||||
case DLL:
|
||||
|
||||
break;
|
||||
case OBJ:
|
||||
_ksys_free(((struct dll *)handle)->h);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
580
src/loader.c
Normal file
580
src/loader.c
Normal file
@@ -0,0 +1,580 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <alloca.h>
|
||||
#include <malloc.h>
|
||||
#include <setjmp.h>
|
||||
#include <envz.h>
|
||||
|
||||
#include <sys/ksys.h>
|
||||
|
||||
#include "loader.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
char *dll_err;
|
||||
|
||||
#define DBG_OUT(format, ...) printf(format, __VA_ARGS__)
|
||||
#define _DBG_ERR(format, ...) sprintf(dll_err, format, __VA_ARGS__);
|
||||
#if DEBUG_INFO
|
||||
#define DBG_ERR(format, ...) _DBG_ERR(format, __VA_ARGS__) DBG_OUT(format, __VA_ARGS__);
|
||||
#define DBG(format, ...) DBG_OUT(format, __VA_ARGS__)
|
||||
#else
|
||||
#define DBG_ERR(format, ...) _DBG_ERR(format, __VA_ARGS__)
|
||||
#define DBG(format, ...)
|
||||
#endif
|
||||
|
||||
static inline int IsPowerOf2(uint32_t val)
|
||||
{
|
||||
if (val == 0)
|
||||
return 0;
|
||||
return (val & (val - 1)) == 0;
|
||||
}
|
||||
|
||||
int validate_pe(void *raw, size_t raw_size, int is_exec)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
|
||||
if (!raw || raw_size < sizeof(IMAGE_DOS_HEADER))
|
||||
return 0;
|
||||
|
||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
|
||||
return 0;
|
||||
|
||||
nt = MakePtr(PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
if ((uint32_t)nt < (uint32_t)raw)
|
||||
return 0;
|
||||
|
||||
if (nt->Signature != IMAGE_NT_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
|
||||
return 0;
|
||||
|
||||
if (is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
|
||||
return 0;
|
||||
|
||||
if (nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
return 0;
|
||||
|
||||
if (is_exec && nt->OptionalHeader.ImageBase != 0)
|
||||
return 0;
|
||||
|
||||
if (nt->OptionalHeader.SectionAlignment < 4096)
|
||||
{
|
||||
if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
|
||||
return 0;
|
||||
}
|
||||
else if (nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
|
||||
return 0;
|
||||
|
||||
if (!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
|
||||
!IsPowerOf2(nt->OptionalHeader.FileAlignment))
|
||||
return 0;
|
||||
|
||||
if (nt->FileHeader.NumberOfSections > 96)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void sec_copy(void *dst, void *src, size_t len)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"shrl $2, %%ecx \n\t"
|
||||
"rep movsl"
|
||||
:
|
||||
: "c"(len), "S"(src), "D"(dst)
|
||||
: "cc");
|
||||
__asm__ __volatile__(
|
||||
"" ::: "ecx", "esi", "edi");
|
||||
};
|
||||
|
||||
static const char *fixName(const char *path)
|
||||
{
|
||||
size_t l = strlen(path);
|
||||
if (l < 31)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else // кароч кринж попытка впихнуть большой путь в маленькую строку
|
||||
{ // в теории должно работать, если в пути <= 15 папок и впринципе они даже будут уникальными
|
||||
char *ret = _ksys_alloc(32);
|
||||
|
||||
sha256_string(path, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void *create_image(void *raw, const char *path)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
PIMAGE_SECTION_HEADER img_sec;
|
||||
|
||||
void *img_base;
|
||||
uint32_t sec_align;
|
||||
int i;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
nt = MakePtr(PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
char *Name = (char *)fixName(path);
|
||||
|
||||
int err = _ksys_shm_open(Name, KSYS_SHM_CREATE, nt->OptionalHeader.SizeOfImage, (char **)&img_base);
|
||||
|
||||
DBG("shm err: %d\n", err);
|
||||
|
||||
if (err == 10 || err == nt->OptionalHeader.SizeOfImage /* этого в доках нет, но экспирементально подтверждается */)
|
||||
{
|
||||
DBG("shm err: %d\n", _ksys_shm_open(Name, KSYS_SHM_OPEN, nt->OptionalHeader.SizeOfImage, (char **)&img_base));
|
||||
}
|
||||
else if (unlikely(img_base != NULL))
|
||||
{
|
||||
|
||||
sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
|
||||
|
||||
sec_align = nt->OptionalHeader.SectionAlignment;
|
||||
|
||||
for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
void *src_ptr;
|
||||
void *dest_ptr;
|
||||
size_t sec_size;
|
||||
|
||||
if (img_sec->SizeOfRawData && img_sec->PointerToRawData)
|
||||
{
|
||||
src_ptr = MakePtr(void *, raw, img_sec->PointerToRawData);
|
||||
dest_ptr = MakePtr(void *, img_base, img_sec->VirtualAddress);
|
||||
sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
|
||||
};
|
||||
|
||||
img_sec++;
|
||||
};
|
||||
|
||||
if (nt->OptionalHeader.DataDirectory[5].Size)
|
||||
{
|
||||
PIMAGE_BASE_RELOCATION reloc;
|
||||
|
||||
uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
|
||||
|
||||
reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
|
||||
nt->OptionalHeader.DataDirectory[5].VirtualAddress);
|
||||
|
||||
while (reloc->SizeOfBlock != 0)
|
||||
{
|
||||
uint32_t cnt;
|
||||
uint16_t *entry;
|
||||
uint16_t reltype;
|
||||
uint32_t offs;
|
||||
|
||||
cnt = (reloc->SizeOfBlock - sizeof(*reloc)) / sizeof(uint16_t);
|
||||
entry = MakePtr(uint16_t *, reloc, sizeof(*reloc));
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
uint16_t *p16;
|
||||
uint32_t *p32;
|
||||
|
||||
reltype = (*entry & 0xF000) >> 12;
|
||||
offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
|
||||
switch (reltype)
|
||||
{
|
||||
case 1:
|
||||
p16 = MakePtr(uint16_t *, img_base, offs);
|
||||
*p16 += (uint16_t)(delta >> 16);
|
||||
break;
|
||||
case 2:
|
||||
p16 = MakePtr(uint16_t *, img_base, offs);
|
||||
*p16 += (uint16_t)delta;
|
||||
break;
|
||||
case 3:
|
||||
p32 = MakePtr(uint32_t *, img_base, offs);
|
||||
*p32 += delta;
|
||||
}
|
||||
entry++;
|
||||
}
|
||||
reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc, reloc->SizeOfBlock);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return img_base;
|
||||
};
|
||||
|
||||
static int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp)
|
||||
{
|
||||
static jmp_buf loader_env;
|
||||
static int recursion = -1;
|
||||
int warn = 0;
|
||||
|
||||
recursion++;
|
||||
if (!recursion)
|
||||
{
|
||||
if (unlikely(setjmp(loader_env) != 0))
|
||||
{
|
||||
recursion = -1;
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
while (imp->Name)
|
||||
{
|
||||
PIMAGE_DOS_HEADER expdos;
|
||||
PIMAGE_NT_HEADERS32 expnt;
|
||||
PIMAGE_EXPORT_DIRECTORY exp;
|
||||
PIMAGE_THUNK_DATA32 thunk;
|
||||
|
||||
void **iat;
|
||||
char *libname;
|
||||
uint32_t *exp_functions;
|
||||
uint16_t *exp_ordinals;
|
||||
char **exp_names;
|
||||
|
||||
const module_t *api;
|
||||
|
||||
libname = MakePtr(char *, imp->Name, img_base);
|
||||
|
||||
DBG("import from %s\n", libname);
|
||||
|
||||
api = load_PE_dll(libname);
|
||||
if (unlikely(api == NULL))
|
||||
{
|
||||
DBG(dll_err, "library %s not found\n", libname);
|
||||
longjmp(loader_env, 1);
|
||||
}
|
||||
|
||||
iat = MakePtr(void **, imp->FirstThunk, img_base);
|
||||
|
||||
if (imp->OriginalFirstThunk != 0)
|
||||
{
|
||||
thunk = MakePtr(PIMAGE_THUNK_DATA32, imp->OriginalFirstThunk, img_base);
|
||||
}
|
||||
else
|
||||
{
|
||||
thunk = MakePtr(PIMAGE_THUNK_DATA32, imp->FirstThunk, img_base);
|
||||
};
|
||||
|
||||
exp = api->img_exp;
|
||||
|
||||
exp_functions = MakePtr(uint32_t *, exp->AddressOfFunctions, api->start);
|
||||
exp_ordinals = MakePtr(uint16_t *, exp->AddressOfNameOrdinals, api->start);
|
||||
exp_names = MakePtr(char **, exp->AddressOfNames, api->start);
|
||||
|
||||
while (thunk->u1.AddressOfData != 0)
|
||||
{
|
||||
PIMAGE_IMPORT_BY_NAME imp_name;
|
||||
|
||||
if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
|
||||
{
|
||||
// ordinal = (*func_list) & 0x7fffffff;
|
||||
// *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
|
||||
// if ((*ImportAddressList) == NULL)
|
||||
// {
|
||||
// DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
|
||||
// RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
|
||||
// return STATUS_ENTRYPOINT_NOT_FOUND;
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
char *export_name;
|
||||
uint16_t ordinal;
|
||||
void *function;
|
||||
uint32_t minn;
|
||||
uint32_t maxn;
|
||||
|
||||
imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
|
||||
thunk->u1.AddressOfData, img_base);
|
||||
*iat = NULL;
|
||||
|
||||
DBG("import %s", imp_name->Name);
|
||||
|
||||
if (imp_name->Hint < exp->NumberOfNames)
|
||||
{
|
||||
export_name = MakePtr(char *, exp_names[imp_name->Hint],
|
||||
api->start);
|
||||
if (strcmp(imp_name->Name, export_name) == 0)
|
||||
{
|
||||
ordinal = exp_ordinals[imp_name->Hint];
|
||||
function = MakePtr(void *, exp_functions[ordinal], api->start);
|
||||
if ((uint32_t)function >= (uint32_t)exp)
|
||||
{
|
||||
printf("forward %s\n", function);
|
||||
warn = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(" \t\tat %x\n", function);
|
||||
*iat = function;
|
||||
};
|
||||
thunk++; // Advance to next thunk
|
||||
iat++;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
|
||||
minn = 0;
|
||||
maxn = exp->NumberOfNames - 1;
|
||||
while (minn <= maxn)
|
||||
{
|
||||
int mid;
|
||||
int res;
|
||||
|
||||
mid = (minn + maxn) / 2;
|
||||
|
||||
export_name = MakePtr(char *, exp_names[mid], api->start);
|
||||
|
||||
res = strcmp(export_name, imp_name->Name);
|
||||
if (res == 0)
|
||||
{
|
||||
ordinal = exp_ordinals[mid];
|
||||
function = MakePtr(void *, exp_functions[ordinal], api->start);
|
||||
|
||||
if ((uint32_t)function >= (uint32_t)exp)
|
||||
{
|
||||
DBG("forward %s\n", function);
|
||||
warn = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(" \t\tat %x\n", function);
|
||||
*iat = function;
|
||||
};
|
||||
break;
|
||||
}
|
||||
else if (minn == maxn)
|
||||
{
|
||||
DBG_ERR("unresolved %s\n", imp_name->Name);
|
||||
warn = 1;
|
||||
break;
|
||||
}
|
||||
else if (res > 0)
|
||||
{
|
||||
maxn = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minn = mid + 1;
|
||||
}
|
||||
};
|
||||
};
|
||||
thunk++; // Advance to next thunk
|
||||
iat++;
|
||||
}
|
||||
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR
|
||||
};
|
||||
|
||||
recursion--;
|
||||
|
||||
if (!warn)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *get_entry_point(void *raw)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
nt = MakePtr(PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
return MakePtr(void *, raw, nt->OptionalHeader.AddressOfEntryPoint);
|
||||
};
|
||||
|
||||
static void *load_lib_internal(const char *path)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
PIMAGE_EXPORT_DIRECTORY exp;
|
||||
|
||||
ksys_ufile_t uf;
|
||||
void *raw_img;
|
||||
size_t raw_size;
|
||||
void *img_base = NULL;
|
||||
|
||||
uf = _ksys_load_file(path);
|
||||
raw_img = uf.data;
|
||||
raw_size = uf.size;
|
||||
|
||||
if (raw_img == NULL)
|
||||
{
|
||||
DBG_ERR("fail load file: %s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (validate_pe(raw_img, raw_size, 0) == 0) // абасрамс
|
||||
{
|
||||
DBG_ERR("invalide module %s\n", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
img_base = create_image(raw_img, path);
|
||||
if (unlikely(img_base == NULL))
|
||||
{
|
||||
DBG_ERR("cannot create image %s\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
_ksys_free(raw_img);
|
||||
|
||||
return img_base;
|
||||
}
|
||||
|
||||
void *get_pe_proc(void *handle, const char *proc_name)
|
||||
{
|
||||
module_t *module = handle;
|
||||
PIMAGE_DOS_HEADER expdos;
|
||||
PIMAGE_NT_HEADERS32 expnt;
|
||||
PIMAGE_EXPORT_DIRECTORY exp;
|
||||
|
||||
uint32_t *exp_functions;
|
||||
uint16_t *exp_ordinals;
|
||||
char **exp_names;
|
||||
|
||||
int minn, maxn;
|
||||
char *export_name;
|
||||
uint16_t ordinal;
|
||||
void *function = NULL;
|
||||
|
||||
exp = module->img_exp;
|
||||
|
||||
exp_functions = MakePtr(uint32_t *, exp->AddressOfFunctions, module->start);
|
||||
exp_ordinals = MakePtr(uint16_t *, exp->AddressOfNameOrdinals, module->start);
|
||||
exp_names = MakePtr(char **, exp->AddressOfNames, module->start);
|
||||
|
||||
minn = 0;
|
||||
maxn = exp->NumberOfNames - 1;
|
||||
while (minn <= maxn)
|
||||
{
|
||||
int mid;
|
||||
int res;
|
||||
|
||||
mid = (minn + maxn) / 2;
|
||||
|
||||
export_name = MakePtr(char *, exp_names[mid], module->start);
|
||||
|
||||
res = strcmp(export_name, proc_name);
|
||||
if (res == 0)
|
||||
{
|
||||
ordinal = exp_ordinals[mid];
|
||||
function = MakePtr(void *, exp_functions[ordinal], module->start);
|
||||
|
||||
if ((uint32_t)function >= (uint32_t)exp)
|
||||
{
|
||||
DBG("forward %s\n", function);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(" \t\tat %x\n", function);
|
||||
};
|
||||
break;
|
||||
}
|
||||
else if (minn == maxn)
|
||||
{
|
||||
DBG("unresolved %s\n", proc_name);
|
||||
break;
|
||||
}
|
||||
else if (res > 0)
|
||||
{
|
||||
maxn = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minn = mid + 1;
|
||||
}
|
||||
};
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
void *load_PE_dll(const char *name)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
PIMAGE_EXPORT_DIRECTORY exp;
|
||||
|
||||
module_t *module, *mod;
|
||||
dll_path_t *dllpath;
|
||||
const char *path = name;
|
||||
int len;
|
||||
char *libname, *tmp;
|
||||
void *img_base;
|
||||
|
||||
img_base = load_lib_internal(path);
|
||||
|
||||
if (unlikely(img_base == NULL))
|
||||
{
|
||||
DBG_ERR("dll_err, unable to load %s\n", name);
|
||||
return 0;
|
||||
};
|
||||
|
||||
module = malloc(sizeof(module_t));
|
||||
|
||||
if (unlikely(module == NULL))
|
||||
{
|
||||
DBG_ERR("%s epic fail: no enough memory\n", __FUNCTION__);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
module->img_name = strdup(libname);
|
||||
module->img_path = strdup(path);
|
||||
module->start = img_base;
|
||||
module->entry = get_entry_point(img_base);
|
||||
module->refcount = 1;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)img_base;
|
||||
nt = MakePtr(PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
|
||||
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
||||
|
||||
module->end = MakePtr(char *, img_base, nt->OptionalHeader.SizeOfImage);
|
||||
|
||||
module->img_hdr = nt;
|
||||
module->img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
|
||||
module->img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
|
||||
nt->OptionalHeader.DataDirectory[0].VirtualAddress);
|
||||
|
||||
if (nt->OptionalHeader.DataDirectory[1].Size)
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR imp;
|
||||
int (*dll_startup)(module_t *mod, uint32_t reason);
|
||||
|
||||
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
|
||||
nt->OptionalHeader.DataDirectory[1].VirtualAddress);
|
||||
|
||||
if (link_image(img_base, imp) == 0)
|
||||
goto err2;
|
||||
|
||||
dll_startup = get_pe_proc(module, "DllStartup");
|
||||
if (dll_startup)
|
||||
{
|
||||
if (0 == dll_startup(module, 1))
|
||||
goto err2;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef DEBUG_INFO
|
||||
printf("module %s %p - %p\n", name, module->start, module->end);
|
||||
#endif
|
||||
return module;
|
||||
|
||||
err2:
|
||||
free(module->img_name);
|
||||
free(module->img_path);
|
||||
free(module);
|
||||
err1:
|
||||
_ksys_free(img_base);
|
||||
return NULL;
|
||||
};
|
||||
39
src/loader.h
Normal file
39
src/loader.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __LOADER_H__
|
||||
#define __LOADER_H__
|
||||
|
||||
#include "pe.h"
|
||||
|
||||
extern char *dll_err;
|
||||
|
||||
void *get_pe_proc(void *handle, const char *proc_name);
|
||||
void *load_PE_dll(const char *name);
|
||||
|
||||
extern char *__appenv;
|
||||
extern int __appenv_size;
|
||||
|
||||
typedef struct tag_module module_t;
|
||||
|
||||
struct tag_module
|
||||
{
|
||||
char *img_name;
|
||||
char *img_path;
|
||||
|
||||
uint32_t refcount;
|
||||
|
||||
char *start;
|
||||
char *end;
|
||||
|
||||
void *entry;
|
||||
|
||||
PIMAGE_NT_HEADERS32 img_hdr;
|
||||
PIMAGE_SECTION_HEADER img_sec;
|
||||
PIMAGE_EXPORT_DIRECTORY img_exp;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *path;
|
||||
int path_len;
|
||||
} dll_path_t;
|
||||
|
||||
#endif // __LOADER_H__
|
||||
187
src/pe.h
Normal file
187
src/pe.h
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned int LONG;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
|
||||
|
||||
#pragma pack(push, 2)
|
||||
typedef struct _IMAGE_DOS_HEADER
|
||||
{
|
||||
WORD e_magic;
|
||||
WORD e_cblp;
|
||||
WORD e_cp;
|
||||
WORD e_crlc;
|
||||
WORD e_cparhdr;
|
||||
WORD e_minalloc;
|
||||
WORD e_maxalloc;
|
||||
WORD e_ss;
|
||||
WORD e_sp;
|
||||
WORD e_csum;
|
||||
WORD e_ip;
|
||||
WORD e_cs;
|
||||
WORD e_lfarlc;
|
||||
WORD e_ovno;
|
||||
WORD e_res[4];
|
||||
WORD e_oemid;
|
||||
WORD e_oeminfo;
|
||||
WORD e_res2[10];
|
||||
LONG e_lfanew;
|
||||
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct _IMAGE_FILE_HEADER
|
||||
{
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
|
||||
#define IMAGE_FILE_DLL 0x2000
|
||||
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 or later processors \
|
||||
and compatible processors */
|
||||
typedef struct _IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER
|
||||
{
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
DWORD ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Win32VersionValue;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
DWORD SizeOfStackReserve;
|
||||
DWORD SizeOfStackCommit;
|
||||
DWORD SizeOfHeapReserve;
|
||||
DWORD SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct _IMAGE_NT_HEADERS
|
||||
{
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
|
||||
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
|
||||
typedef struct _IMAGE_SECTION_HEADER
|
||||
{
|
||||
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
|
||||
union
|
||||
{
|
||||
DWORD PhysicalAddress;
|
||||
DWORD VirtualSize;
|
||||
} Misc;
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfRawData;
|
||||
DWORD PointerToRawData;
|
||||
DWORD PointerToRelocations;
|
||||
DWORD PointerToLinenumbers;
|
||||
WORD NumberOfRelocations;
|
||||
WORD NumberOfLinenumbers;
|
||||
DWORD Characteristics;
|
||||
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
|
||||
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
|
||||
#define IMAGE_SCN_MEM_SHARED 0x10000000
|
||||
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000
|
||||
|
||||
#pragma pack(push, 4)
|
||||
typedef struct _IMAGE_BASE_RELOCATION
|
||||
{
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfBlock;
|
||||
} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct _IMAGE_IMPORT_DESCRIPTOR
|
||||
{
|
||||
union
|
||||
{
|
||||
DWORD Characteristics;
|
||||
DWORD OriginalFirstThunk;
|
||||
};
|
||||
DWORD TimeDateStamp;
|
||||
DWORD ForwarderChain;
|
||||
DWORD Name;
|
||||
DWORD FirstThunk;
|
||||
} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
|
||||
|
||||
typedef struct _IMAGE_THUNK_DATA32
|
||||
{
|
||||
union
|
||||
{
|
||||
DWORD ForwarderString;
|
||||
DWORD Function;
|
||||
DWORD Ordinal;
|
||||
DWORD AddressOfData;
|
||||
} u1;
|
||||
} IMAGE_THUNK_DATA32, *PIMAGE_THUNK_DATA32;
|
||||
|
||||
typedef struct _IMAGE_IMPORT_BY_NAME
|
||||
{
|
||||
WORD Hint;
|
||||
BYTE Name[1];
|
||||
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
|
||||
|
||||
#define IMAGE_ORDINAL_FLAG 0x80000000
|
||||
|
||||
typedef struct _IMAGE_EXPORT_DIRECTORY
|
||||
{
|
||||
DWORD Characteristics;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD Name;
|
||||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
DWORD AddressOfFunctions;
|
||||
DWORD AddressOfNames;
|
||||
DWORD AddressOfNameOrdinals;
|
||||
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
#define MakePtr(cast, ptr, addValue) (cast)((uint32_t)(ptr) + (uint32_t)(addValue))
|
||||
188
src/sha256.c
Normal file
188
src/sha256.c
Normal file
@@ -0,0 +1,188 @@
|
||||
|
||||
#include "sha256.h"
|
||||
#include <string.h> // Для memcpy, memset
|
||||
#include <stdio.h> // Для snprintf в bytes_to_hex
|
||||
|
||||
// --- Внутренние макросы и константы SHA-256 ---
|
||||
|
||||
// Ротации
|
||||
#define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
|
||||
|
||||
// Логические функции
|
||||
#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define SIGMA0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define SIGMA1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define sigma0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))
|
||||
#define sigma1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))
|
||||
|
||||
// Начальные значения хеша (H0-H7)
|
||||
static const uint32_t H_INIT[8] = {
|
||||
0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
|
||||
0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL};
|
||||
|
||||
// Константы раундов (K0-K63)
|
||||
static const uint32_t K[64] = {
|
||||
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
|
||||
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
|
||||
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
|
||||
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
|
||||
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
|
||||
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
|
||||
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
|
||||
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL};
|
||||
|
||||
// --- Вспомогательные функции ---
|
||||
|
||||
// Обработка одного 64-байтового блока
|
||||
static void sha256_transform(uint32_t H[8], const uint8_t block[64])
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t a, b, c, d, e, f, g, h;
|
||||
uint32_t t1, t2;
|
||||
int i;
|
||||
|
||||
// 1. Преобразование 16 32-битных слов из блока (big-endian)
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
W[i] = (uint32_t)block[i * 4] << 24 |
|
||||
(uint32_t)block[i * 4 + 1] << 16 |
|
||||
(uint32_t)block[i * 4 + 2] << 8 |
|
||||
(uint32_t)block[i * 4 + 3];
|
||||
}
|
||||
|
||||
// 2. Расширение до 64 слов
|
||||
for (i = 16; i < 64; i++)
|
||||
{
|
||||
W[i] = sigma1(W[i - 2]) + W[i - 7] + sigma0(W[i - 15]) + W[i - 16];
|
||||
}
|
||||
|
||||
// 3. Инициализация рабочих переменных
|
||||
a = H[0];
|
||||
b = H[1];
|
||||
c = H[2];
|
||||
d = H[3];
|
||||
e = H[4];
|
||||
f = H[5];
|
||||
g = H[6];
|
||||
h = H[7];
|
||||
|
||||
// 4. Основной цикл (64 раунда)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
t1 = h + SIGMA1(e) + Ch(e, f, g) + K[i] + W[i];
|
||||
t2 = SIGMA0(a) + Maj(a, b, c);
|
||||
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
// 5. Добавление результатов к текущему хешу
|
||||
H[0] += a;
|
||||
H[1] += b;
|
||||
H[2] += c;
|
||||
H[3] += d;
|
||||
H[4] += e;
|
||||
H[5] += f;
|
||||
H[6] += g;
|
||||
H[7] += h;
|
||||
}
|
||||
|
||||
// --- API функции ---
|
||||
|
||||
void sha256_init(SHA256_CTX *ctx)
|
||||
{
|
||||
memcpy(ctx->H, H_INIT, sizeof(H_INIT));
|
||||
ctx->buffer_len = 0;
|
||||
ctx->total_len_bits = 0;
|
||||
}
|
||||
|
||||
void sha256_update(SHA256_CTX *ctx, const uint8_t *data, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
ctx->total_len_bits += len * 8; // Обновляем общую длину в битах
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
size_t copy_len = 64 - ctx->buffer_len; // Сколько байт нужно для заполнения буфера
|
||||
if (copy_len > len)
|
||||
{
|
||||
copy_len = len;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer + ctx->buffer_len, data, copy_len);
|
||||
ctx->buffer_len += copy_len;
|
||||
data += copy_len;
|
||||
len -= copy_len;
|
||||
|
||||
if (ctx->buffer_len == 64)
|
||||
{
|
||||
sha256_transform(ctx->H, ctx->buffer);
|
||||
ctx->buffer_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(SHA256_CTX *ctx, uint8_t digest[32])
|
||||
{
|
||||
// 1. Добавление "1" бита
|
||||
ctx->buffer[ctx->buffer_len++] = 0x80;
|
||||
|
||||
// 2. Добавление нулей, пока не останется 8 байтов для длины
|
||||
if (ctx->buffer_len > 56)
|
||||
{
|
||||
// Если места не хватает, заполняем текущий блок нулями и обрабатываем его
|
||||
memset(ctx->buffer + ctx->buffer_len, 0x00, 64 - ctx->buffer_len);
|
||||
sha256_transform(ctx->H, ctx->buffer);
|
||||
ctx->buffer_len = 0;
|
||||
}
|
||||
// Заполняем оставшуюся часть буфера нулями до 56 байтов
|
||||
memset(ctx->buffer + ctx->buffer_len, 0x00, 56 - ctx->buffer_len);
|
||||
|
||||
// 3. Добавление длины сообщения в битах (big-endian, 64-бит)
|
||||
// Длина уже в ctx->total_len_bits
|
||||
ctx->buffer[56] = (uint8_t)(ctx->total_len_bits >> 56);
|
||||
ctx->buffer[57] = (uint8_t)(ctx->total_len_bits >> 48);
|
||||
ctx->buffer[58] = (uint8_t)(ctx->total_len_bits >> 40);
|
||||
ctx->buffer[59] = (uint8_t)(ctx->total_len_bits >> 32);
|
||||
ctx->buffer[60] = (uint8_t)(ctx->total_len_bits >> 24);
|
||||
ctx->buffer[61] = (uint8_t)(ctx->total_len_bits >> 16);
|
||||
ctx->buffer[62] = (uint8_t)(ctx->total_len_bits >> 8);
|
||||
ctx->buffer[63] = (uint8_t)(ctx->total_len_bits);
|
||||
|
||||
// 4. Обработка последнего блока
|
||||
sha256_transform(ctx->H, ctx->buffer);
|
||||
|
||||
// 5. Копирование финального хеша в digest (big-endian)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
digest[i * 4] = (uint8_t)(ctx->H[i] >> 24);
|
||||
digest[i * 4 + 1] = (uint8_t)(ctx->H[i] >> 16);
|
||||
digest[i * 4 + 2] = (uint8_t)(ctx->H[i] >> 8);
|
||||
digest[i * 4 + 3] = (uint8_t)(ctx->H[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_string(const char *input_string, uint8_t digest[32])
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, (const uint8_t *)input_string, strlen(input_string));
|
||||
sha256_final(&ctx, digest);
|
||||
}
|
||||
|
||||
void bytes_to_hex(const uint8_t *bytes, size_t len, char *hex_string)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
sprintf(hex_string + (i * 2), "%02x", bytes[i]);
|
||||
}
|
||||
hex_string[len * 2] = '\0'; // Завершаем строку
|
||||
}
|
||||
30
src/sha256.h
Normal file
30
src/sha256.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
#include <stddef.h> // Для size_t
|
||||
#include <stdint.h> // Для uint8_t, uint32_t, uint64_t
|
||||
|
||||
// Контекст для пошагового хеширования
|
||||
typedef struct {
|
||||
uint8_t buffer[64]; // Буфер для неполного 64-байтового блока
|
||||
uint32_t buffer_len; // Длина данных в буфере
|
||||
uint64_t total_len_bits; // Общая длина входных данных в битах
|
||||
uint32_t H[8]; // Текущие значения хеша (H0-H7)
|
||||
} SHA256_CTX;
|
||||
|
||||
// Инициализирует контекст SHA256
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
|
||||
// Обновляет хеш-значение данными
|
||||
void sha256_update(SHA256_CTX *ctx, const uint8_t *data, size_t len);
|
||||
|
||||
// Завершает хеширование и получает 32-байтовый дайджест
|
||||
void sha256_final(SHA256_CTX *ctx, uint8_t digest[32]);
|
||||
|
||||
// Вспомогательная функция для хеширования всей строки сразу
|
||||
void sha256_string(const char *input_string, uint8_t digest[32]);
|
||||
|
||||
// Вспомогательная функция для преобразования байтов в шестнадцатеричную строку
|
||||
void bytes_to_hex(const uint8_t *bytes, size_t len, char *hex_string);
|
||||
|
||||
#endif // SHA256_H
|
||||
36
tests/test.c
Normal file
36
tests/test.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char path[256];
|
||||
char fName[256];
|
||||
const char *error;
|
||||
|
||||
printf("dll: ");
|
||||
scanf("%s", &path);
|
||||
|
||||
void *handle = dlopen(path, RTLD_LAZY);
|
||||
if (!handle)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("fName:");
|
||||
scanf("%s", fName);
|
||||
|
||||
void (*f)() = dlsym(handle, fName);
|
||||
if ((error = dlerror()) != NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", error);
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OK\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user