Are you tired of hacking?, take some rest here.
Just help me out with my small experiment regarding memcpy performance.
after that, flag is yours.
http://pwnable.kr/bin/memcpy.c
ssh memcpy@pwnable.kr -p2222 (pw:guest)
해킹이 아니라고? 쉬울것 같은 예감이 든다 ^~^--> 아니었다 ㅎㅎ
// 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@ubuntu:~$ cat readme
the compiled binary of "memcpy.c" source code (with real flag) will be executed under memcpy_pwn privilege if you connect to port 9022.
execute the binary by connecting to daemon(nc 0 9022).
오 그냥 실행만 하면 되는군 하고
실행시켜서 입력값을 대충 넣어봣더니
중간에 짤려버린다 ㅂㄷ..
이번엔 5번째 까지 가다가 끊겼다
뭐지..
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");
}
저기서 오류가 나서 끊기는게 아닌가 싶다.
이코드만 무사히 통과하면 flag를 볼 수 있을 것 같다.
(푸는중)
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;
}
slow_memcpy는 그냥 복사하듯이 값을 하나씩 옮긴다
fast_memcpy는 일단 어셈으로 짜여있다 한번 자세히 보도록하자
// 64-byte block fast copy
??64byte블록이란느 말이있어서 일단 염두에 두었다
if(len) slow_memcpy(dest, src, len);
len이 0이아니면 slow_memcpy를 한번 더 돌아서 64비트로 나눈 나머지를 cpy해줘야한다
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;
}
movdqa와 movntps가 뭔지 찾아보았따
SSE병렬 프로그래밍이라는게 있는데
128bit씩 한꺼번에 연산을 한다고 한다
속도가 엄청 빨라지는 연산이다
여기서 movdqa move alinged double quard word의 줄임말으로써
128bit 레지스터나 메모리에 정렬된 값을 옮길때 쓰는 명령어다(정렬되지 않았을 떄는 movdqu)
(정렬된 메모리의 연산이 훨씬 빠르기 떄문에 연산 전에 정렬을 해준다고 한다)
http://www.slideshare.net/KooKyeongWon/0204-sse
MOVNTPS - Non-temporal store of four packed single-precision floatingpoint values from an XMM register into memory
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 double quadword in the source operand (second operand) to the destination operand (first operand) using a non-temporal hint to minimize cache pollution during the write to memory. The source operand is an XMM register, which is assumed to contain four packed single-precision floating-point values. The destination operand is a 128-bit memory location.
The non-temporal hint is implemented by using a write combining (WC) memory type protocol when writing the data to memory. Using this protocol, the processor does not write the data into the cache hierarchy, nor does it fetch the corresponding cache line from memory into the cache hierarchy. The memory type of the region being written to can override the non-temporal hint, if the memory address specified for the non-temporal store is in an uncacheable (UC) or write protected (WP) memory region.
Because the WC protocol uses a weakly-ordered memory consistency model, a fencing operation such as SFENCE should be used in conjunction with MOVNTDQ instructions if multiple processors might use different memory types to read/write the memory location.
그니까 movadq에서 데이터를 레지스터로 옮기고 movntdq에서 레지스터에서 메모리로 데이터를 옮기는 것 같다
이 연산을 16bit 4블록을 동시에 옮기는데 그래서 64비트 단위 인것 같다.
그리고 movadq에서 <정렬된 데이터>라는 의미는 주솟값이 64의 배수라는 뜻 인것 같다
즉 정렬되지 않았을 떄는 에러를 일으킨다
src가 정렬되 있는 데이터이기 때문에 des가 정렬되어 있지 않으면 데이터가 오버플러우 되거나 세그먼트 폴트가 나타날 것이다
복사해서 한번 돌려보자
gcc로 컴파일 할떄 -lm을 붙여줘야한다
pow함수 때문
이럴땐, gcc source.c -lm
-lm을 링크해야 하는 이유
: man 페이지에서 해당 함수를 위해 사용해야 할 별도의 라이브러리가 있는지 확인해 합니다.
libm.a 라이브러리를 지정해줘야 math.h 에 있는 pow() 를 쓸 수 있다.
(참고) libc.a 는 gcc 에서 기본적으로 include 된다.
http://blog.daum.net/_blog/BlogTypeView.do?blogid=0SsSt&articleno=210
근데 컴파일이 에러하나 없이 잘되더라..
윗줄에
// compiled with : gcc -o memcpy memcpy.c -m32 -lm
0x080486f0에서 에러가 난다
따라갔다
여기서 에러가 난댄다
...
답답해서 고민하다가
memcpy.c에 des주소를 출력하는 소스를 추가해봤따
des가 0x8071058로 시작되서
정렬이 안되있어서 에러가 났다
끝이 8이기 때문ㅇ 0으로 만들어주려면 8이 더필요했다
32에다 8을 덯나 40을 넣어줬다
조금씩 수정하면서 계속해봤따32
오 한칸 더갔다
계속해보자
계속하다보니 8씩 더해서 넣어주면 되는것 같다
플래그 땄다!!!
이제 nc 0 9022로 해보자
길어서 짤리는데
암튼 플래그땄다
값은 8 16 40 72 136 264 520 1032 2056 5004
넣었다
ㅠㅠ감격ㄱ 이제 rookiss풀러가야지~
'war game > pwnable.kr' 카테고리의 다른 글
pwnable.kr tiny_easy 30pt (0) | 2016.10.18 |
---|---|
pwnable.kr simple login 50pt (0) | 2016.10.18 |
pwnable.kr codemap 10pt (0) | 2016.10.12 |
pwnable.kr uaf 8pt (0) | 2016.10.12 |
pwnable.kr cmd2 9pt (0) | 2016.10.12 |