서브웨이

pwnable.kr memcpy 풀이 본문

Pwnable/pwnable.kr

pwnable.kr memcpy 풀이

샌드위치메이커 2020. 9. 22. 21:37

뭔가 쉬어가는 문제랍니다.

평소와는 다르게 리드미 파일이 있네요. 읽어봅시다.

일단 여기있는 소스코드는 보기용 파일이고 진짜 실행을 위한 소스코드는 9022 포트로 접속하면 있답니다.

 

일단 소스코드를 봅시다.

// compiled with : gcc -o memcpy memcpy.c -m32 -lm
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <math.h>

unsigned long long rdtsc(){
        asm("rdtsc");
}

char* slow_memcpy(char* dest, const char* src, size_t len){
	int i;
	for (i=0; i<len; i++) {
		dest[i] = src[i];
	}
	return dest;
}

char* fast_memcpy(char* dest, const char* src, size_t len){
	size_t i;
	// 64-byte block fast copy
	if(len >= 64){
		i = len / 64;
		len &= (64-1);
		while(i-- > 0){
			__asm__ __volatile__ (
			"movdqa (%0), %%xmm0\n"
			"movdqa 16(%0), %%xmm1\n"
			"movdqa 32(%0), %%xmm2\n"
			"movdqa 48(%0), %%xmm3\n"
			"movntps %%xmm0, (%1)\n"
			"movntps %%xmm1, 16(%1)\n"
			"movntps %%xmm2, 32(%1)\n"
			"movntps %%xmm3, 48(%1)\n"
			::"r"(src),"r"(dest):"memory");
			dest += 64;
			src += 64;
		}
	}

	// byte-to-byte slow copy
	if(len) slow_memcpy(dest, src, len);
	return dest;
}

int main(void){

	setvbuf(stdout, 0, _IONBF, 0);
	setvbuf(stdin, 0, _IOLBF, 0);

	printf("Hey, I have a boring assignment for CS class.. :(\n");
	printf("The assignment is simple.\n");

	printf("-----------------------------------------------------\n");
	printf("- What is the best implementation of memcpy?        -\n");
	printf("- 1. implement your own slow/fast version of memcpy -\n");
	printf("- 2. compare them with various size of data         -\n");
	printf("- 3. conclude your experiment and submit report     -\n");
	printf("-----------------------------------------------------\n");

	printf("This time, just help me out with my experiment and get flag\n");
	printf("No fancy hacking, I promise :D\n");

	unsigned long long t1, t2;
	int e;
	char* src;
	char* dest;
	unsigned int low, high;
	unsigned int size;
	// allocate memory
	char* cache1 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
	char* cache2 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
	src = mmap(0, 0x2000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

	size_t sizes[10];
	int i=0;

	// setup experiment parameters
	for(e=4; e<14; e++){	// 2^13 = 8K
		low = pow(2,e-1);
		high = pow(2,e);
		printf("specify the memcpy amount between %d ~ %d : ", low, high);
		scanf("%d", &size);
		if( size < low || size > high ){
			printf("don't mess with the experiment.\n");
			exit(0);
		}
		sizes[i++] = size;
	}

	sleep(1);
	printf("ok, lets run the experiment with your configuration\n");
	sleep(1);

	// run experiment
	for(i=0; i<10; i++){
		size = sizes[i];
		printf("experiment %d : memcpy with buffer size %d\n", i+1, size);
		dest = malloc( size );

		memcpy(cache1, cache2, 0x4000);		// to eliminate cache effect
		t1 = rdtsc();
		slow_memcpy(dest, src, size);		// byte-to-byte memcpy
		t2 = rdtsc();
		printf("ellapsed CPU cycles for slow_memcpy : %llu\n", t2-t1);

		memcpy(cache1, cache2, 0x4000);		// to eliminate cache effect
		t1 = rdtsc();
		fast_memcpy(dest, src, size);		// block-to-block memcpy
		t2 = rdtsc();
		printf("ellapsed CPU cycles for fast_memcpy : %llu\n", t2-t1);
		printf("\n");
	}

	printf("thanks for helping my experiment!\n");
	printf("flag : ----- erased in this source code -----\n");
	return 0;
}

 분명 쉬어가는 문제랬는데 코드가 깁니다.... 그리고 컴파일 방법을 알려주는것을 보니 뭔가 수정을 해서 직접 컴파일을 해서 방법을 알아내야하나봅니다.

차근차근 읽어보니 memcpy 방식의 차이에 대한 시간차를 마지막까지 성공적으로 비교하여 플래그값을 얻어내는 것이 목표네요.

slow_memcpy는 말그대로 한바이트씩 차례로 복사하는 방식이고 fast_memcpy는 64바이트 블록단위로 인라인 어셈블리어를 사용해서 복사를 진행하네요. 

인라인 어셈블리 사용법은 이곳을 참조하시면 쉽게 이해가 가능합니다.

recipes.egloos.com/5345910

 

인라인 어셈블러를 사용하려면?

뭘 알아야 이해를 하지 씨 언어로 만든 프로그램에다 어셈블러 명령어를 삽입하는 것을 인라인 어셈블러라고 해요. 인라인 어셈블러를 사용하는 목적이 무엇일까요? 우선 효율적인 프로그램을

recipes.egloos.com

 

일단 MOVDQA와 MOVNTPS가 무엇인지 알아야겠죠?

www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc183.htm

 

MOVDQA--Move Aligned Double Quadword

MOVDQA - Move Aligned Double Quadword Opcode Instruction Description 66 0F 6F /r MOVDQA xmm1, xmm2/m128 Move aligned double quadword from xmm2/m128 to xmm1. 66 0F 7F /r MOVDQA xmm2/m128, xmm1 Move aligned double quadword from xmm1 to xmm2/m128. Description

www.jaist.ac.jp

www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc197.htm

 

MOVNTPS--Move Aligned Four Packed Single-FP Non Temporal

MOVNTPS--Move Aligned Four Packed Single-FP Non Temporal Opcode Instruction Description 0F 2B /r MOVNTPS m128, xmm Move packed single-precision floating-point values from xmm to m128, minimizing pollution in the cache hierarchy. Description Moves the doubl

www.jaist.ac.jp

이곳을 확인하면 무엇인지 나와있습니다. 물론 영어이긴 하지만 잘 해석하면 이해하기 어렵지 않습니다.

MOVDQA는 Move Aligned Double Quadword의 약자로, 정렬된 Double Quadword(2(Double) x 4(Quad) x 2바이트(word) = 16바이트)단위의 xmm레지스터/메모리로 부터 xmm레지스터/메모리로 복사합니다. 만약 정렬이 되어있지 않으면 예외가 발생합니다. 정렬에 관한 내용은 아래 블로그를 참조하시면 될 것 같습니다.

3dmpengines.tistory.com/1807

 

SIMD 로 배열 copy 작성__declspec(align(16)) 과 movdqu, movdqa

movdqu mov : asm 에서의 mov 와 유사한 의미 dq : double quad (word) 로 quad word는 word 의 4배 인 8 byte 와 앞의 double 이 붙어 2*8 = 총 16 바이트인데 word 가 기본 pack 사이즈를 말함으로 2바이트씩..

3dmpengines.tistory.com

MOVNTPS는 Move Aligned Four Packed Single-FP Non Temporal의 약자로 간단히 말하면 정렬된 실수를 복사하는 비슷한 명령인 듯 합니다. 정확한 의미는 이해하기 어렵네요...

 

한번 어떻게 돌아가는지 시험해봅시다.

128부터 뭔가 진행이 안됩니다. 아까 정렬이 안되어있으면 오류가 난다고 했으니 인라인 어셈블리에서 사용하는 src와 dest 값에서 문제가 생겼을 가능성이 높아보입니다. 한번 소스코드를 수정해서 src와 dest를 출력해봅시다.

그런데.... 문제가 생겼습니다.

그냥 되어버립니다. 이유를 모르겠습니다. 이래선 문제를 해결할 수가 없습니다...ㅠㅠㅠ 그래서 그냥 다른 분들의 블로그를 참조했습니다...ㅠ

문제는 역시 정렬이 되지 않아 발생한 것이었습니다... 사이즈 64 이후로 src 주소의 끝이 8이 되어야 사이즈가 고정이 되고 다음 src가 0으로 시작이 되는데 0이 되어 문제가 발생한 것 같습니다. 그럼 8로 끝나도록 정렬해줍시다.

예 뭐 이걸 풀었다고 해야할지 애매합니다. 일단 다음에 시간나면 다시한번 풀어봐야겠습니다.

'Pwnable > pwnable.kr' 카테고리의 다른 글

pwnable.kr uaf 풀이  (0) 2020.08.26
pwnable.kr cmd2 풀이  (0) 2020.08.24
pwnable.kr cmd1 풀이  (0) 2020.08.24
pwnable.kr lotto 풀이  (0) 2020.08.21
pwnable.kr blackjack 풀이  (0) 2020.08.19
Comments