메모리에서 일부 코드를 실행하고 싶습니다. 장기적 목표는 자체 해독 앱을 만드는 것입니다. 내가 뿌리부터 시작한 문제를 이해하기. 은 다음 코드 생성 : 내가 segfault의-오류 그러나C : 메모리에서 기계 코드를 실행하십시오.
#define UNENCRYPTED true
#define sizeof_function(x) ((unsigned long) (&(endof_##x)) - (unsigned long) (&x))
#define endof_function(x) void volatile endof_##x() {}
#define DECLARE_END_OF_FUNCTION(x) void endof_##x();
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
unsigned char *bin;
#ifdef UNENCRYPTED
void hexdump(char *description, unsigned char *toDump, unsigned long length) {
printf("Hex-dump of \"%s\":\n", description);
for (int i = 0; i < length; i++) {
printf("%02x", toDump[i]);
}
printf("\n");
}
void hello_world() {
printf("Hello World!\n");
}
endof_function(hello_world);
#endif
int main (void) {
errno = 0;
unsigned long hello_worldSize = sizeof_function(hello_world);
bin = malloc(hello_worldSize);
//Compute the start of the page
size_t pagesize = sysconf(_SC_PAGESIZE);
uintptr_t start = (uintptr_t) bin;
uintptr_t end = start + (hello_worldSize);
uintptr_t pagestart = start & -pagesize;
bin = (void *)pagestart;
//Set mprotect for bin to write-only
if(mprotect(bin, end - pagestart, PROT_WRITE) == -1) {
printf("\"mprotect\" failed; error: %s\n", strerror(errno));
return(1);
}
//Get size and adresses
unsigned long hello_worldAdress = (uintptr_t)&hello_world;
unsigned long binAdress = (uintptr_t)bin;
printf("Address of hello_world %lu\nSize of hello_world %lu\nAdress of bin:%lu\n", hello_worldAdress, hello_worldSize, binAdress);
//Check if hello_worldAdress really points to hello_world()
void (*checkAdress)(void) = (void *)hello_worldAdress;
checkAdress();
//Print memory contents of hello_world()
hexdump("hello_world", (void *)&hello_world, hello_worldSize);
//Copy hello_world() to bin
memcpy(bin, (void *)hello_worldAdress, hello_worldSize);
//Set mprotect for bin to read-execute
if(mprotect(bin, end - pagestart, PROT_READ|PROT_EXEC) == -1) {
printf("\"mprotect\" failed; error: %s\n", strerror(errno));
return(1);
}
//Check if the contents at binAdress are the same as of hello_world
hexdump("bin", (void *)binAdress, hello_worldSize);
//Execute binAdress
void (*executeBin)(void) = (void *)binAdress;
executeBin();
return(0);
}
을; 프로그램의 출력은 다음과 같다 :
(OS의 X에, i86-64) : 4,294,970,639
Size of hello_world 17
Adress of bin:4296028160
Hello World!
Hex-dump of "hello_world":
554889e5488d3d670200005de95a010000
Hex-dump of "bin":
554889e5488d3d670200005de95a010000
Program ended with exit code: 9
그리고 내 Raspi (32 비트 ARM 리눅스)에 그래서 hello_world의
ADRESS :
Adress of hello_world 67688
Size of hello_world 36
Hello World!
Hello World!
Hex-dump of "hello_world":
00482de90db0a0e108d04de20c009fe512ffffeb04008de50bd0a0e10088bde8d20b0100
Hex-dump of "bin":
00482de90db0a0e108d04de20c009fe512ffffeb04008de50bd0a0e10088bde8d20b0100
Speicherzugriffsfehler //This is german for memory access error
내 실수는 어디에서 왔습니까?
문제가 있었다, 그래서 hello_world에서 printf와 통화는 물론 복사 기능이 작동하지 않습니다 상대 점프 주소, 기준입니다. 테스트 목적으로 나는에 그래서 hello_world 변경 :
int hello_world() {
//_printf("Hello World!\n");
return 14;
}
과에 "// binAdress 실행"아래의 코드 :
int (*executeBin)(void) = (void *)binAdress;
int test = executeBin();
printf("Value: %i\n", test);
이되는 출력한다 (14) : D ARM에
x64로 컴파일 된 스 니펫은 'e95a010000'으로 끝나며 다른 주소로 점프합니다. 이 점프의 대상은 점프 명령 자체의 주소와 관련하여 계산됩니다. 어셈블리 코드를 메모리의 다른 위치에 복사 할 때 점프 대상이 엉망이되었습니다. – DCoder
좋아, 내가이 권리를 얻는다면 printf를 printf에 대한 절대적인 참조로 대체해야 할 필요가 있겠는가? –
예,이 방법으로이 문제를 해결할 수 있습니다. – DCoder