create it

покачто не умеет открывать зависимости других библиотек
This commit is contained in:
2025-12-17 12:35:34 +05:00
commit ae3c87bc06
13 changed files with 1369 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.a
*.o
*.dll
*.kex

23
.vscode/c_cpp_properties.json vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}