我有一个C++类; 这个课程如下:
首先,标题:
class PageTableEntry {
public:
PageTableEntry(bool modified = true);
virtual ~PageTableEntry();
bool modified();
void setModified(bool modified);
private:
PageTableEntry(PageTableEntry &existing);
PageTableEntry &operator=(PageTableEntry &rhs);
bool _modified;
};
Run Code Online (Sandbox Code Playgroud)
和.cpp文件
#include "PageTableEntry.h"
PageTableEntry::PageTableEntry(bool modified) {
_modified = modified;
}
PageTableEntry::~PageTableEntry() {}
bool PageTableEntry::modified() {
return _modified;
}
void PageTableEntry::setModified(bool modified) {
_modified = modified;
}
Run Code Online (Sandbox Code Playgroud)
我在.cpp文件中涉及_modified的所有3行设置断点,这样我就可以确切地看到它们被设置/更改/读取的位置.顺序如下:
每个PageTableEntry实例都会出现这种情况.类本身并没有改变变量 - 其他东西是.不幸的是,我不知道是什么.该类是使用new动态创建的,并且被传递(作为指针)到各种STL结构,包括向量和映射.我的代码永远不会调用mutator(我还没有达到这一点)并且STL结构不应该这样,并且因为断言器永远不会在mutator上被调用,所以我只能假设它们不是.
显然,在某些情况下,私有变量可以在不经过类的变换器的情况下进行更改,由谁知道什么情况触发,但我无法想象它可能是什么.有什么想法吗?
UPDATE:的值这在每个阶段:
构造1:0x100100210
构造2:0x100100400
访问器1:0x1001003f0
访问器2:0x100100440
UPDATE2 :(
代码显示访问PageTableEntry的位置)
// In constructor:
_tableEntries = std::map<unsigned int, PageTableEntry *>();
// …Run Code Online (Sandbox Code Playgroud) 我知道我可以通过引用复制该函数,但我想了解以下代码中发生的段错误.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int return0()
{
return 0;
}
int main()
{
int (*r0c)(void) = malloc(100);
memcpy(r0c, return0, 100);
printf("Address of r0c is: %x\n", r0c);
printf("copied is: %d\n", (*r0c)());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我认为应该起作用的心理模型.
该进程拥有分配给r0c的内存.我们正在复制与return0对应的数据段中的数据,并且复制成功.
我认为解除引用函数指针与调用函数指针指向的数据段相同.如果是这种情况,那么指令指针应该移动到对应于r0c的数据段,其中包含函数return0的指令.对应于return0的二进制代码不包含任何依赖于return0的地址的跳转或函数调用,所以它应该只返回0并且恢复ip ... 100个字节对于函数指针肯定已经足够了,并且0xc3很好在r0c的范围内(它在字节11处).
那么为什么分段错误呢?这是对C函数指针的语义的误解,还是有一些安全功能阻止了我不知道的自修改代码?
据我了解,编写并随后执行 JIT 或自修改代码的一般、更抽象的过程如下所示。
从这篇关于 x86 上自修改代码的文章中我可以看出,手动缓存管理显然是没有必要的。我认为 aclflushopt是必要的,但 x86 1显然会在从具有新指令的位置加载时自动处理缓存失效,这样指令提取就永远不会过时。我的问题不是关于 x86,但我想将其包括在内以进行比较。
AArch64 中的情况稍微复杂一些,因为它区分了可共享域以及缓存操作的“可见性”程度。仅从 ARMv8/ARMv9 的官方文档中,我首先得出了这个猜测。
dsb ishst确保在继续之前已全部写入,isb sy确保从内存中提取后续指令。但DMB/DSB/ISB 的文档说“ISB 后面的指令是从缓存或内存中获取的”。这给我的印象是缓存控制操作确实是必要的。我的新猜测是这样的。
dsb ishst确保在继续之前已全部写入,ic ivau新代码占用的所有缓存行。但我又忍不住觉得这也不太对劲。过了一会儿,我在文档中发现了一些我错过的东西,并且在一篇论文中发现了几乎相同的东西。他们都给出了一个看起来像这样的例子。
dc cvau, Xn ; Clean cache to PoU, so the newly written code will be visible
dsb ish ; Wait for cleaning to finish
ic ivau, Xn ; Invalidate …Run Code Online (Sandbox Code Playgroud) 假设我有如下所示的 x86-64 代码(尽管这个问题更普遍地适用于所有代码):
mov rbx,7F0140E5247Dh
jmp rbx
Run Code Online (Sandbox Code Playgroud)
如果目标值未对齐,而该代码可以执行,则覆盖目标常量是否安全?换句话说,我可以观察到部分更新的跳转目标,从而导致跳转到不存在的地址吗?此外,如果目标常量跨越页面或缓存行边界,这是否安全?
编辑:
我只对更改单个指令感兴趣,而不是更改指令边界位置。
我正在寻找几行代码来展示x86汇编程序中的自修改代码以用于教育目的(不需要做一些有意义的事情,但需要清楚地编写自己的代码,然后在阅读代码本身时执行它).
我确实浏览了一下Web,但所有的例子要么过于复杂,要么就是不太明显.我可能错过了正确的去处,所以随时建议链接或代码.
对于安全类,我应该为一个程序编写自修改代码,该程序在磁盘上找到自己的可执行文件,读取二进制数据,并在将其写回磁盘之前对其进行加密。这应该像一种多态病毒,它会改变自己以欺骗检测已知签名的防病毒扫描程序。
我已经准备好了所有的部分:
/proc/self/exe.我的问题是我能够打开可执行文件的唯一方法是在 read-only mode "rb"。如果我尝试以模式打开文件进行写入,"wb"或者"r+b"我返回错误"Text file busy"。无论如何,我是否可以在 C 中写入进程自己的可执行文件?我可以通过以某种方式更改权限来做到这一点吗?
编辑:我想要完成的是有一个可执行文件,它会在每次运行时对其自身的一部分进行加密,以便在每次运行后都有一个新的校验和。
从可执行二进制文件读取数据后,如何写回它或删除它并用具有相同文件名的新文件替换它?
我想在获取下一条指令之前修改它,在foo 函数中的这篇文章的最佳答案中,*p指向 main 函数中的下一条指令。我想修改where*p指向的内容。例如我想将下一条指令更改为跳转指令。我怎样才能做到这一点?
void foo()
{
void** p = search((void**)&p, __builtin_return_address(0));
// modify content of where *p points at.
}
int main()
{
foo();
//next instruction. *p points here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想在 intel Core-i7 3632QM 处理器上使用 gcc 编译器来执行此操作。
我正在尝试学习一些堆栈溢出技术并在其中使用shellcode.我能够成功使用一些基本的shellcode.然后我开始exeve在程序集中使用并调用ls -l它,再次成功.现在我尝试使用相对寻址并在我的代码中删除空值.因此我尝试了一个简单的自修改代码.我知道代码段是只读的,所以我试着调用mprotect它使它可写.我的代码仍然不起作用,我得到分段错误movb %al, 0x7(%esi).如果有人可以让我对我的代码中出错的东西有所了解,我真的很感激.
.text
.globl _start
_start:
jmp StartPoint
execvecall:
popl %esi # the address of string
#calling mprotect to make the memory writable
movl $0x7d, %eax
movl %esi, %ebx
movl $0x20, %ecx
movl $7, %edx
int $0x80
xorl %eax, %eax
movb %al, 0x7(%esi) #putting zero for at the end of /bin/ls
movb %al, 0xa(%esi) #putting another zero at the end of -l
#this part forms an array ending with for …Run Code Online (Sandbox Code Playgroud) 我想研究和摆弄自修改函数,并知道 JavaScript 具有eval和其他有趣的反射特性,例如使函数从内部打印其主体,我想我想做一些自修改函数测试使用 JavaScript。
我想要一个简单的函数,当被调用时,它会根据任何规则修改自身。
就像也许某个函数可以先执行一个简单的操作console.log,然后下次调用它时它就会执行此操作alert。这显然可以通过 来实现if,但我在这里寻找的是实际的物理函数首先应该如下所示:
function selfm()
{
console.log('hello')
// + modify self here somehow
}
Run Code Online (Sandbox Code Playgroud)
第一次通话后:
function selfm()
{
alert('hello')
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能以最简单的形式实现这种行为?
问题:
我制作了一个自我修改其字节之一的elf可执行文件.它只是将1更改为1.当我正常运行可执行文件时,我可以看到更改成功,因为它完全按预期运行(更多关于更进一步下来).调试时出现问题:调试器(使用radare2)在查看修改后的字节时返回错误的值.
语境:
我做了一个逆向工程挑战,受到了最小精灵的启发.您可以在那里看到"源代码"(如果您甚至可以称之为):https://pastebin.com/Yr1nFX8W.
汇编和执行:
nasm -f bin -o tinyelf tinyelf.asm
chmod +x tinyelf
./tinyelf [flag]
Run Code Online (Sandbox Code Playgroud)
如果标志是正确的,则返回0.任何其他值表示您的答案是错误的.
./tinyelf FLAG{wrong-flag}; echo $?
Run Code Online (Sandbox Code Playgroud)
...输出"255".
!解决方案SPOILERS!
可以静态反转它.完成后,您会发现通过执行此计算可以找到标志中的每个字符:
flag[i] = b[i] + b[i+32] + b[i+64] + b[i+96];
Run Code Online (Sandbox Code Playgroud)
...其中i是字符的索引,b是可执行文件本身的字节.这是一个ac脚本,可以在没有调试器的情况下解决问题:
#include <stdio.h>
int main()
{
char buffer[128];
FILE* fp;
fp = fopen("tinyelf", "r");
fread(buffer, 128, 1, fp);
int i;
char c = 0;
for (i = 0; i < 32; i++) {
c = buffer[i];
// handle self-modifying code
if …Run Code Online (Sandbox Code Playgroud) python debugging assembly reverse-engineering self-modifying
我想复制并调用一个函数,但是在调用缓冲区时,下面的代码会出现段错误.我需要改变什么?(Linux,x86)
#include <string.h>
#include <malloc.h>
#include <stdio.h>
int foo () { return 12; }
void foo_end () {}
int main () {
int s = (unsigned long long) foo_end - (unsigned long long) foo;
int (*f) () = (int (*)()) malloc (s);
memcpy ((void*) f, (const void*) foo, s);
printf ("%d %d\n", f (), foo ());
}
Run Code Online (Sandbox Code Playgroud)
编辑:工作解决方案:
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
int foo () { return 12; }
void foo_end () {} …Run Code Online (Sandbox Code Playgroud) 我有一个1500万行.csv文件.它包括一些只有连字符的行.但是用excel,记事本或记事本++打开这个文件是不可能的.因此我认为要在C#中进行修改(首先读入,然后写出作为未建立连字符行的新修改文件).
我怎样才能以最简单的方式编写代码?
在运行时,汇编程序或机器代码(它是什么?)应该在RAM中的某个位置.我可以以某种方式访问它,读取甚至写入它吗?
这仅用于教育目的.
所以,我只能编译这段代码.我真的在这里读书吗?
#include <stdio.h>
#include <sys/mman.h>
int main() {
void *p = (void *)main;
mprotect(p, 4098, PROT_READ | PROT_WRITE | PROT_EXEC);
printf("Main: %p\n Content: %i", p, *(int *)(p+2));
unsigned int size = 16;
for (unsigned int i = 0; i < size; ++i) {
printf("%i ", *((int *)(p+i)) );
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我补充一下
*(int*)p =4;
Run Code Online (Sandbox Code Playgroud)
那是一个分段错误.
从答案中,我可以构造以下代码,在运行时修改它自己:
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
void * alignptr(void * ptr, uintptr_t alignment) {
return (void *)((uintptr_t)ptr & ~(alignment …Run Code Online (Sandbox Code Playgroud) self-modifying ×13
assembly ×7
c ×5
x86 ×3
c++ ×2
linux ×2
arm64 ×1
atomic ×1
bigdata ×1
binary ×1
c# ×1
cpu-cache ×1
csv ×1
debugging ×1
eval ×1
function ×1
gcc ×1
instructions ×1
javascript ×1
jit ×1
permissions ×1
pointers ×1
private ×1
python ×1
reflection ×1
security ×1
system-calls ×1
variables ×1