作为一个学习练习,我试图保存php文件的编译状态,以便以后执行它而不必zend_compile_file再次执行.
我做的第一件事是写一个钩子的扩展zend_compile_file.如果请求是在未编译的文件(即:file.php)上进行的,则会将zend_op_array数据转储到另一个文件(即:compiled-file.php).如果请求是在这样的编译文件上进行的,它会将数据加载到新的zend_op_array中然后返回它.
为简单起见,我忽略了与类和函数相关的所有内容,因此我不希望我的扩展适用于包含这些内容的脚本.但我认为其他更简单的脚本应该可行吗?
好吧,它适用于非常简单的脚本,但通常它只是挂起并达到最大执行时间限制.我发现它总是在错误的条件分支上失败.例如,这个脚本可以工作:
<?php
$a = 10;
$b = 5;
if ($b < $a)
echo $a;
Run Code Online (Sandbox Code Playgroud)
虽然这个会挂起:
<?php
$a = 10;
$b = 5;
if ($b > $a)
echo $a;
Run Code Online (Sandbox Code Playgroud)
我的问题:我是否正确假设对于没有函数或类的简单脚本,制作zend_op_array的深层副本并返回它应该足以复制php编译?如果没有,我应采取的其他步骤是什么?
以下是我的扩展的相关文件: opdumper.c oploader.c
编辑:我设法通过更改此代码"修复"我的问题:
void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
fwrite(&type, sizeof(type), 1, fp);
switch(type) {
case IS_UNDEF:
case IS_UNUSED:
break;
...
}
}
Run Code Online (Sandbox Code Playgroud)
到这一个:
void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
fwrite(&type, sizeof(type), 1, fp);
switch(type) {
case IS_UNDEF:
case …Run Code Online (Sandbox Code Playgroud) 目前正在学习堆利用,但有些奇怪我不明白:
这是通过调用malloc(0x80)分配的下一个块:
0x602090: 0x0000000000000000 0x0000000000000091
0x6020a0: 0x00007ffff7dd1b78 0x0000000000601120
...
Run Code Online (Sandbox Code Playgroud)
在此之后调用另一个malloc(0x80),我的目标是返回0x601130.这有效,但仅限于0x601128 == 0x90:
0x601120: 0x0000000000602010 0x0000000000000090
0x601130: 0x0000000000602130 0x00000000006021c0
Run Code Online (Sandbox Code Playgroud)
如果我将90更改为任何其他值,则会导致内存损坏:
*** Error in `censored': malloc(): memory corruption: 0x00000000006021d0 **
...
#0 0x00007ffff7a42428 in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff7a4402a in __GI_abort () at abort.c:89
#2 0x00007ffff7a847ea in __libc_message (do_abort=0x2, fmt=fmt@entry=0x7ffff7b9de98 "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff7a8f13e in malloc_printerr (ar_ptr=0x7ffff7dd1b20 <main_arena>, ptr=0x6021d0,
str=0x7ffff7b9acff "malloc(): memory corruption", action=<optimized out>) at malloc.c:5006
#4 _int_malloc (av=av@entry=0x7ffff7dd1b20 <main_arena>, bytes=bytes@entry=0x80) at malloc.c:3474 …Run Code Online (Sandbox Code Playgroud) 我试图通过从头开始编写一个elf可执行文件来了解elf标准.使用以下代码,Elf32没有造成太大问题:
BITS 32
org 0x08048000
ehdr: ; Elf32_Ehdr
db 0x7F, "ELF", 1, 1, 1, 2 ; e_ident
times 8 db 0
dw 2 ; e_type
dw 3 ; e_machine
dd 1 ; e_version
dd _start ; e_entry
dd phdr - $$ ; e_phoff
dd 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr …Run Code Online (Sandbox Code Playgroud) 我正在尝试将dll注入软件中以绕开它的ExtTextOut函数.注入和绕行很有效(我正在使用Microsoft Detours),但是当我尝试修改ExtTextOut函数时,一切都出错了.
这是我的代码:
#pragma comment(lib, "detours.lib")
#include <Windows.h>
#include <detours.h>
#include <tchar.h>
BOOL (WINAPI * Real_ExtTextOutW)(HDC hdc, int x, int y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx) = ExtTextOutW;
BOOL WINAPI Mine_ExtTextOutW(HDC hdc, int x, int y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx)
{
// The expected results would be that every characters displayed become "z"
return Real_ExtTextOutW(hdc, x, y, fuOptions, lprc, L"z", 1, lpDx);
}
BOOL APIENTRY …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习如何破解文件格式,所以我从一个简单的例子开始,我从那里开始:如何读取/写入二进制文件中的结构?
#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
typedef struct student
{
char name[10];
double age;
vector<int> grades;
}student_t;
void readBinaryFile(string filename)
{
ifstream input_file(filename, ios::binary);
student_t master[3];
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < 3; idx++)
{
// If you wanted to search for specific records,
// you should do it here! if (idx == 2) ...
cout << "Record #" << idx << endl;
//cout << "Capacity: " << master[idx].grades.capacity() << …Run Code Online (Sandbox Code Playgroud) 我试图读取文件,但我意识到它将失败,因为即使文件比我要读取的文件大得多,我也会尝试读取过多的数据。
该文件为120 MB,我的ifstream失败时为12967字节(即使它在12801时开始表现异常)。
这是说明我的问题的代码:
#include <fstream>
#include <iostream>
#include <Windows.h>
using std::ifstream;
using std::cout;
#define CORRECT_SIZE 12800
#define CORRECT_BUT_WIERD 12966
#define INCORRECT_SIZE 12967
bool check_error_bits(ifstream* f);
int main()
{
ifstream myFile("myfile.txt");
char c[CORRECT_SIZE];
char c2[CORRECT_BUT_WIERD];
char c3[INCORRECT_SIZE];
/*
* TEST A (works fine)
*/
myFile.seekg(0, std::ios_base::beg);
myFile.read(c, CORRECT_SIZE);
check_error_bits(&myFile);
cout << myFile.tellg() << std::endl; // Here, tellg() returns 12800
/*
* TEST B (works too, but acts wierd)
*/
myFile.seekg(0, std::ios_base::beg);
myFile.read(c2, CORRECT_BUT_WIERD);
check_error_bits(&myFile);
cout << myFile.tellg() << std::endl; // …Run Code Online (Sandbox Code Playgroud) 我发现在 c 中编译时与在 c++ 中编译时存在差异,但我不完全理解......假设我声明了一个大小为 5 的 char 数组:
char my_array[5];
Run Code Online (Sandbox Code Playgroud)
根据我的理解,“my_array”实际上是一个 char 指针,它允许我这样做:
char* a = my_array;
Run Code Online (Sandbox Code Playgroud)
现在,我明白,当我声明数组时,我只分配了 5 个字节(其中每个值一个字节),这意味着“&my_array”不应该存在,因为没有为指向 my_array 的指针分配内存。为了证明这一点,我这样做了:
char* b = &my_array; // compiler error in c++, not in c
char** c = &my_array; // compiler error in c++, not in c
Run Code Online (Sandbox Code Playgroud)
我不明白其中的区别,为什么 c 会允许这样做?不过,假设我想将 char[5] 转换为 char*,而不使用 a 的方法,我发现我也可以这样做:
char* c = (char*)&my_array; // works both in c and c++
Run Code Online (Sandbox Code Playgroud)
那个我实在是看不懂。我没有确定“&my_array”不存在吗?更令人担忧的是,这两行返回相同的精确值:
// a and c have the same value (both in c and c++) …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
正如标题所说,我想从最小化的窗口捕获图像......甚至可能吗?我使用msdn 的CaptureAnImage,它可以工作,除非窗口最小化.
我尝试过的一个解决方案是最大化它,捕获图像,然后将其恢复到原始状态.唯一的问题是动画看起来很难看,我想找个替代方案......以下是我试过的方法:
WINDOWPLACEMENT wInfo;
UINT originalPlacement;
GetWindowPlacement(hWnd, &wInfo);
originalPlacement = wInfo.showCmd;
wInfo.showCmd = SW_MAXIMIZE;
SetWindowPlacement(hWnd, &wInfo);
wInfo.showCmd = originalPlacement;
CaptureAnImage(hWnd); // Capture the image while it's maximized
SetWindowPlacement(hWnd, &wInfo);
Run Code Online (Sandbox Code Playgroud)
所以我在这里寻找其中一个解决方案:
是否有可能在图像最小化时捕获图像?
要么
是否可以最大化它,捕获它,然后将其恢复到原始状态而不显示任何类型的动画?
PS:我在搜索我的问题时找到了链接,但它在c#中,我无法在c ++中使用它...