Tag: x86

使用回调函数来报告堆栈回溯

假设我有以下内容: typedef struct { char *name; char binding; int address; } Fn_Symbol //definition of function symbol static Fn_Symbol *fnSymbols; //array of function symbols in a file statc int total; //number of symbol functions in the array and file static void PrintBacktrace(int sigum, siginfo_t * siginfo, void *context) { printf(“\nSignal received %d (%s)\n”, signum, strsignal(signum)); const […]

在gcc内联asm中data32 data32 nopw%cs:0x0(%rax,%rax,1)指令是什么意思?

在为gcc编译器的-O2优化运行一些测试时,我在函数的反汇编代码中观察到以下指令: data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1) 这个指令做了什么? 为了更详细,我试图了解编译器如何使用O2优化优化无用的递归,如下所示: int foo(void) { return foo(); } int main (void) { return foo(); } 上面的代码在没有优化的情况下编译时导致堆栈溢出,但适用于O2优化代码。 我认为使用O2它完全删除了推送函数foo的堆栈,但为什么data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)需要? 0000000000400480 : foo(): 400480: eb fe jmp 400480 400482: 66 66 66 66 66 2e 0f data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1) 400489: 1f 84 00 […]

在保护模式下设置中断(x86)

为保护模式设置中断的过程是什么? 这个链接说应该: 为中断描述符表腾出空间 告诉CPU该空间在哪里(参见GDT教程:lidt的工作方式与lgdt完全相同) 告诉PIC您不再需要使用BIOS默认值(请参阅编程PIC芯片) 为IRQ和exception编写几个ISR处理程序(请参阅中断服务程序) 将ISR处理程序的地址放在适当的描述符中 启用IRQ掩码中所有支持的中断(PIC) 第三步对我没有任何意义(我查看了这个链接,但没有任何关于告诉PIC的事情)所以我忽略了它并完成了接下来的两个步骤,当我到达最后一步时再次无能为力。 但是,根据我对中断的理解,我不理解的两个步骤都与PIC控制器的硬件中断有关,不应该影响PIT在IRQ 0上引发的中断。因此我也忽略了这一步骤。 当我运行我的代码时,它编译得很好,甚至在虚拟机中运行,但中断似乎只发射一次。 然后我意识到我没有向EOI发送EOI,以防止它再引发任何中断。 但是,在iret指令使虚拟机崩溃之前,添加mov al, 0x20和out 0x20, al 。 这是我的IDT: ; idt idt_start : dw 0x00 ; The interrupt handler is located at absolute address 0x00 dw CODE_SEG ; CODE_SEG points to the GDT entry for code db 0x0 ; The unused byte db 0b11101001 […]

x86代码从x64进程注入x86进程

我意识到标题有点令人费解,所以让我解释一下我要做的事情: 我刚刚编写了一个简单的DLL注入器,用于我正在尝试编写的概念certificate。 该程序获取当前进程的快照,枚举进程树,并将DLL注入其直接父进程。 现在,在理想条件下,工作正常:32位版本的注入器可以注入到32位父进程中,64位版本的注入器可以注入到64位父进程中。 不过,我现在要做的是从x64注入器向32位父进程注入32位DLL。 一旦注入了DLL,我就希望再注入一个由注入的DLL导出的函数。 不过,我不确定是否真的可以做到。 (我已经汇总了一些代码来确定父进程是32位进程还是64位进程,所以这不是问题) 现在,我已经找到了一些代码,它们似乎通过将预编译的机器代码注入到流程中来完成第一部分。 (至少,我认为这就是它正在做的事情)通常,在注入对LoadLibraryW的调用之后,我将获得该调用返回的地址,将相对偏移量添加到我想要调用的导出函数,并注入一个调用function。 在这种情况下,我无法将32位库加载到我的64位注入器中,因此我无法像通常那样使用GetProcAddress找到函数的相对偏移量。 我通过以下方式解决了这个问题: 由于我无法使用常规方法找到32位DLL的函数偏移量,因此我正在将文件读入缓冲区,使用该缓冲区填充IMAGE_NT_HEADERS32结构,并枚举IMAGE_EXPORT_DIRECTORY以查找名称和相对偏移量所有导出的function。 所以在这一点上,我有以下内容: 32位DLL加载到32位进程中 在32位进程中运行以下代码时,该值等效于funcAddr: 码: HMODULE hInjectedDLL = LoadLibrary(“mydll.dll”); DWORD funcAddr = (DWORD)GetProcAddress(hInjectedDLL, “ExportedFunc”) – (DWORD)hInjectedDLL; 从理论上讲,我现在需要的只是hInjectedDLL的值,我应该可以调用该函数。 但遗憾的是,我对组装或机器代码知之甚少,知道如何获得该值。 有任何想法吗? (另外,我知道通过编译两个版本的注入器可以省去很多麻烦,当父进程的处理器架构不匹配时,让一个运行另一个版本。我试图避免去不过这条路线。) 编辑 :想想它可能有助于解释我在这个概念certificate中实际想要完成的事情。 我正在尝试一个想法,我必须允许在当前控制台中执行子进程,而不需要原始进程等待子进程完成。 由于在控制台应用程序中没有用于执行此操作的内置API,因此您通常会遇到一个进程树,所有进程都在等待各自的子进程完成。 为了实现此function,我想执行以下操作: 注射 DLL注入器将扮演“执行进程”的角色。 (通常必须等到子进程完成的进程)运行时,它确定其父进程的平台,以及父进程是否甚至是基于控制台的应用程序。 如果不是,则该过程仅使用exec系列函数来运行所需的子进程,立即退出。 如果父进程是控制台应用程序,则进程确定要使用的DLL,挂起最初创建注入进程的线程,然后将DLL注入父进程。 解决我们的职能 一旦DLL就位,注入器就会确定DLL导出的函数的地址。 (通常,我通过调用CreateRemoteThread来执行初始注入,然后在该线程上使用GetExitCodeThread来获取父进程中DLL的基址。一旦我有了这个,就可以通过简单的算法找到地址我们导出的函数,然后我可以使用它来注入该函数的第二次调用。 呼唤我们的function 导出的函数将类似于: BOOL RewriteHProcess(HANDLE hProcess) 注入器将再次使用CreateRemoteThread从父进程的上下文调用此函数,其中hProcess是注入器进程的句柄。 在DLL方面,该函数会做两件事之一(我不太确定我的第一个想法是否可行,考虑到跨线程的内存访问的安全限制,所以我把第二个想法放在一起,如果首先没有成功。) RewriteHProcess将打开先前挂起的线程进行读写,并使用ReadProcessMemory ,它将在进程的内存中搜索HANDLE到我们的注入器进程。 (我们假设父进程当前正在阻止使用WaitForSingleObject函数进一步执行。我知道命令提示符至少会执行,而这是我目前关注的焦点)然后DLL调用内部函数创建我们想要的子进程,关闭旧句柄,并使用新子进程的句柄覆盖内存。 […]

具有自动存储持续时间的两个不同对象在地址比较下是否相等?

特别是,允许​​不同函数中两个自动变量的地址比较如下: sink.c #include #include void sink(void *l, void *r) { puts(l == r ? “equal” : “not equal”); exit(0); } main.c中 typedef struct { char x[32]; } Foo; void sink(void *l, void *r); Foo make(void *p) { Foo f2; sink(&f2, p); return f2; } int main() { Foo f1 = make(&f1); } 我希望这打印not equal因为f1和f2是不同的对象。 使用gcc我得到的not […]

解释AF标志在x86指令中的工作原理?

我有一个小的8086模拟器,我有一个长期的错误2年,现在AF在sub内部表现不正常并添加说明。 我目前计算其值的方法是8位数和减法: uint8_t base=… , subt=… base=base&0xF; subt=subt&0xF; //isolate bottom nibble if((int16_t)base-subt>7 || (int16_t)base-subt<-7){ flags.af=1; }else{ flags.af=0; } (假设像sub base,subt这样的指令) 并添加它是这样的: uint8_t base=… , adder=… base=base&0xF; adder=adder&0xF; //isolate bottom nibble if(base+adder>7 || base+adder<-7){ flags.af=1; }else{ flags.af=0; } (对于像add base,adder这样的指令) 如何正确计算模拟器中的AF标志以获取此类指令?

论证传递如何运作?

我想知道如何将参数传递给C中的函数。 存储的值在哪里以及如何检索它们? 可变参数传递如何工作? 此外,因为它是相关的:返回值怎么样? 我对CPU寄存器和汇编器有基本的了解,但还不足以让我彻底了解GCC向我吐出的ASM。 一些简单的带注释的例子将非常受欢迎。

rdtsc,周期太多了

#include static inline unsigned long long tick() { unsigned long long d; __asm__ __volatile__ (“rdtsc” : “=A” (d) ); return d; } int main() { long long res; res=tick(); res=tick()-res; printf(“%d”,res); return 0; } 我用gcc编译了这段代码-O0 -O1 -O2 -O3优化。 我总是得到2000-2500个周期。 任何人都可以解释这个输出的原因吗? 如何度过这些周期? 第一个函数“tick”是错误的。 这是对的 。 另一个版本的function“滴答” static __inline__ unsigned long long tick() { unsigned hi, lo; […]

如何使用SSE执行uint32 / float转换?

在SSE中有一个函数_mm_cvtepi32_ps(__m128i input) ,它接受32位宽的有符号整数( int32_t )的输入向量,并将它们转换为float s。 现在,我想将输入整数解释为未签名。 但是没有函数_mm_cvtepu32_ps ,我找不到一个实现。 你知道我在哪里可以找到这样的function,或者至少对实现有所暗示吗? 为了说明结果的差异: unsigned int a = 2480160505; // 10010011 11010100 00111110 11111001 float a1 = a; // 01001111 00010011 11010100 00111111; float a2 = (signed int)a; // 11001110 11011000 01010111 10000010

混合C和汇编文件

我想使用g ++在我的C ++程序中使用裸函数 。 不幸的是,与VC ++不同,g ++不支持裸函数,管理它的唯一方法是在单独的文件中编写自己的汇编代码并与C ++文件链接。 我试图找到一些很好的x86教程来混合汇编和C / C ++文件,但找不到任何好的。 如果您知道任何问题,请告诉我。 请注意,除了在C或程序集中使用它们之外,我不是要求内联汇编而是链接C和汇编文件以及在汇编中声明C的外部变量的方法,反之亦然,以及使用Makefile链接C和asm文件的方法。