Pwnable之[Toddler's Bottle](三)--memcpy

Pwnable之[Toddler’s Bottle](三)–memcpy

提示是:
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.

黑累了吗?放松一下吧,就帮我个小忙,测试下关于memcpy的性能,flag就是你的。
看代码:

// compiled with : gcc -o memcpy memcpy.c -m32 -lm
#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     64字节块快速复制(用xmm汇编的方式)
    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);//如果小于64位的话调用slow_memcpy逐字复制
    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");//嘿,我有一个无聊的CS课程作业。
    printf("The assignment is simple.\n");//这个作业很简单

    printf("-----------------------------------------------------\n");
    printf("- What is the best implementation of memcpy?        -\n");//什么是最好的memcpy实现方式
    printf("- 1. implement your own slow/fast version of memcpy -\n");//试验你自己的快/慢版memcpy
    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  //设置实验参数 从2^3~2^13
    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);//指定的memcpy的量在low~high之间
        scanf("%d", &size);
        if( size < low || size > high ){
            printf("don't mess with the experiment.\n");//不满足则退出
            exit(0);
        }
        sizes[i++] = size;//将你输入的实验参数放入size数组
    }

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

    // run //开始实验
    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    逐个byte的内存复制
        t2 = rdtsc();
        printf("ellapsed CPU cycles for slow_memcpy : %llu\n", t2-t1);//CUP运算时间

        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);//CUP运算时间
        printf("\n");
    }

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

看代码,可以很清晰的了解程序的逻辑。
要你输入10次长度不同的bit,并且每次要满足不同的范围,不满足就退出。
然后分别用slow_memcpy()和fast_memcpy()慢快两种内存复制方式计算你输入长度的内存复制所花的时间。
运行10次后获得falg。

程序清楚了,那就直接开始测试下:
先吧memcpy复制到自己的机子。
安装下38位的编译环境:
yum install glibc-devel.i686
按题目提示编译:gcc -o memcpy memcpy.c -m32 -lm
测试下:
这里写图片描述
发现运行到第4次运算的时候停止了。

具体什么原因不知道,那就gdb调试下。
还是随便输入:
这里写图片描述
发现程序在 movntps 这个指令上出现异常。
百度下这个指令:
这里写图片描述

得到提示:内存地址必须是16字节对齐的。
而我们知道前面我们输入size也就是新malloc的内存空间大小。
那么只要保证我们输入的size所创建的内存空间是16字节对齐的,不可以了吗?

再查了下malloc的内存对齐方式, 是8字节对齐的。
那么当我们输入9时,就有2*8=16也就对齐了。
因为有个默认有个4字节的头部。
所以其创建的公式是:((j+4)/8+1)*8
j是我们输入的size

按这个思想写python爆破大致符合的size:

for i in range(4,14):
    low = pow(2,i-1)
    high = pow(2,i)
    #print low,high
    n=0

    for j in range(low+1,high):
        if(n==4):
            break

        k=((j+4)/8+1)*8
        if((k)%16==0 or (k)%16>=9):
            print j,
            n=n+1
    print ".........ok"

输出满足的4个size
然后。。。
这里写图片描述
这里写图片描述
这是我按输出的随机选的。
这里写图片描述

参考文章:
https://blog.csdn.net/misskissc/article/details/17717717
https://www.cnblogs.com/dongzhiquan/p/5621906.html
https://blog.csdn.net/celerychen2009/article/details/8839104
https://www.cnblogs.com/p4nda/p/7162378.html
https://blog.csdn.net/xiaominkong123/article/details/51733528

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值