【pwnable.kr】 memcpy
pwnable的新一题,和堆分配相关。
http://pwnable.kr/bin/memcpy.c
ssh memcpy@pwnable.kr -p2222 (pw:guest)
我觉得主要考察的是堆块分配问题。
推荐《C和C++安全编码》
首先通过阅读源代码,看一下题目大意。
// 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=; 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 >= ){
i = len / ;
len &= (-); while(i-- > ){
__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 += ;
src += ;
}
} // byte-to-byte slow copy
if(len) slow_memcpy(dest, src, len);
return dest;
} int main(void){ setvbuf(stdout, , _IONBF, );
setvbuf(stdin, , _IOLBF, ); 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(, 0x4000, , MAP_PRIVATE|MAP_ANONYMOUS, -, );
char* cache2 = mmap(, 0x4000, , MAP_PRIVATE|MAP_ANONYMOUS, -, );
src = mmap(, 0x2000, , MAP_PRIVATE|MAP_ANONYMOUS, -, ); size_t sizes[];
int i=; // setup experiment parameters
for(e=; e<; e++){ // 2^13 = 8K
low = pow(,e-);
high = pow(,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();
}
sizes[i++] = size;
} sleep();
printf("ok, lets run the experiment with your configuration\n");
sleep(); // run experiment
for(i=; i<; i++){
size = sizes[i];
printf("experiment %d : memcpy with buffer size %d\n", i+, 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 ;
}
题目是这样的,首先请用户输入10个数字,分别位于2的各次幂之间。
输入之后,根据用户输入的数据使用malloc函数,在堆上请求大小为用户输入数据的堆块。
然后,分别用slow_memcpy和fast_memcpy两种方式,对堆块内的数据向另外一个内存地址拷贝,并比较二者时间。
slow_memcpy使用的是最复杂的循环赋值,而fast_memcpy使用的是汇编指令movdqa进行拷贝。
当全部10数字拷贝结束后打印flag。
坑点在于全部的以mmap申请的空间基本对题目没有什么影响。
先运行一下,随意输入10个符合要求的数字,运行终止,出现段错误
并不清楚为什么,使用gdb调试一下看看:
结果显示出错位置在fast_memcpy函数中的movntps汇编语句上
也就是说是movntps执行出了问题,各寄存器值如下:
具体看一下movntps是做什么的
也就是把之前从src中拷贝到XMM寄存器中的数据传递给新申请的栈块。
要求是必须对其16字节
一.什么是字节对齐,为什么要对齐?
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
16字节对齐的意思就是地址的末位必须为0,比如0xabcdef10,就是16字节对齐。
所以出错的原因是edx中的数据非16进制对齐数据(0x804c4a8)
因此,这道题的关键是构造每次申请的堆块地址都是16进制对齐数据。
堆块是由链表结构组成的,dlalloc系列的堆块结构图和分配过程可参看《C和C++安全编码》,堆块有一明显特征是堆块除了用户数据外还有堆块大小和标志位共计4字节。而malloc分配的堆块大小是以8字节对其的。
假设用户申请的堆块大小是a的话,malloc(a)分配的堆块大小为 8*(int((a+4)/8)+1)。
因此假设第一个malloc分配地址是16字节对齐的,则每次请求大小为16字节对齐的数据块即可成功运行结束。
以如下脚本可检测是否,malloc分配的字节大小是16字节对齐的
# coidng = utf-8
while(1):
a = raw_input()
a = int(a)
if (a+4)%16>=9 || (a+4)%16==0:
print a," is ok"
else:
print a," is wrong"
因此,只要每次输入数字前先用脚本测试一下,基本就可以通过验证。
服务器上的代码在另外一个文件夹下,用nc命令连接
nc 0 9022后就可以输入了:
在检测的python脚本里留下了许多不行的数据:
【pwnable.kr】 memcpy的更多相关文章
- 【pwnable.kr】 asm
一道写shellcode的题目, #include <stdio.h> #include <string.h> #include <stdlib.h> #inclu ...
- 【pwnable.kr】 [simple login]
Download : http://pwnable.kr/bin/login Running at : nc pwnable.kr 9003 先看看ida里面的逻辑. 比较重要的信息时input变量再 ...
- 【pwnable.kr】 brainfuck
pwnable.kr第二关第一题: ========================================= Download : http://pwnable.kr/bin/bfDownl ...
- 【pwnable.kr】 unlink
pwnable.kr 第一阶段的最后一题! 这道题目就是堆溢出的经典利用题目,不过是把堆块的分配与释放操作用C++重新写了一遍,可参考<C和C++安全编码一书>//不是广告 #includ ...
- 【pwnable.kr】 codemap
pwnable新的一题. download: http://pwnable.kr/bin/codemap.exe ssh codemap@pwnable.kr -p2222 (pw:guest) 这道 ...
- 【pwnable.kr】 uaf
目测是比较接近pwnable的一道题.考察了uaf(use after free的内容),我觉得说白了就是指针没有初始化的问题. ssh uaf@pwnable.kr -p2222 (pw:guest ...
- 【pwnable.kr】input
这道题是一道一遍一遍满足程序需求的题. 网上其他的题解都是用了C语言或者python语言的本地调用,我想联系一下pwntools的远程调用就写了下面的脚本, 执行效果可以通过1~4的检测,到最后soc ...
- 【pwnable.kr】cmd2
这道题是上一个cmd1的升级版 ssh cmd2@pwnable.kr -p2222 (pw:mommy now I get what PATH environmentis for :)) 登录之后, ...
- 【pwnable.kr】cmd1
最近的pwnable都是linux操作系统层面的. ssh cmd1@pwnable.kr -p2222 (pw:guest) 首先还是下载源代码: #include <stdio.h> ...
随机推荐
- R语言 table()函数
table函数 用 table() 函数统计因子各水平的出现次数(称为频数或频率).也可以对一般的向量统计每个不同元素的出现次数.如 sex = c("女","女&quo ...
- vue动画钩子
<template> <div class="hello"> <div class="toggle" @click="f ...
- C语言中的结构体是怎么定义的_怎么使用?
结构体的定义 // 定义结构体st struct st{ int a; // 成员a int b; // 成员b }; #include <stdio.h> struct st{ int ...
- Swift-如何快速学习Swift
关于本文: 1.说明本文写作的目的 2.整理了Swift的基本语法树 3.看图作文 一.写作目的 昨天看了一个知识专栏,作者讲述的是“如何研究性的学习”.整个课程1个小时9分钟,花了我19块人民币.其 ...
- INI文件,WritePrivateProfileString()和GetPrivateProfileString()函数----转载
INI文件就是扩展名为“ini”的文件.在Windows系统中,INI文件是很多,最重要的就是“System.ini”.“System32.ini”和“Win.ini”.该文件主要存放用户所做的选择以 ...
- java并发初探ThreadPoolExecutor拒绝策略
java并发初探ThreadPoolExecutor拒绝策略 ThreadPoolExecuter构造器 corePoolSize是核心线程池,就是常驻线程池数量: maximumPoolSize是最 ...
- 二十三、java连接oracle数据库操作:jdbc
1.jdbc 1) 含义:JDBC是java语言连接数据库,Java Date Base Connectivity2) jdbc的本质:在编程时java程序会去连接不同的数据库,而每个数据库的底层的实 ...
- Mybatis入门(一)环境搭建
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...
- sqlserver查找断号,回收单据号
declare @L varchar(20), @R varchar(20), @Len int, @FromNo int, @F1 intselect @L='19011', @R='', @Len ...
- 二十 Filter&自动登录功能
Filter过滤器 过滤器,其实就是对客户端发出来的请求进行过滤,浏览器发出,然后服务器用Servelt处理.在中间就可以过滤,起到的是拦截的作用. 不仅仅作用于客户端请求,而且过滤服务器响应 作用: ...