[pwnable.kr]第一题fd

题目

  • 标题: fd
    (fd在Linux中是文件描述符的意思,但是在此题中我没看到题干和fd有什么关系.)
  • 文字描述 :
Mommy! what is a file descriptor in Linux?

ssh [email protected] -p2222 (pw:guest)

提示使用ssh登录服务器pwnable.kr, 端口-p2222.账号fd, 密码guest

  • 用secureCRT登录查看


    ls查看.PNG

第一步:ls -l查看文件和权限,看到三个文件col col.c flag

尝试用cat flag查看flag文件,发现权限不足(其实从在从ls -l给的信息中也能看出来文件flag的权限给的很少)
第二步:查看源代码cat col.c

catcol.PNG

解题思路

  • 第一步 : 分析源代码
    首先, 我们可以看到代码中包含有我们获取flag文件的命令, 即
system("/bin/cat flag");

根据源代码中的if语句约束, 为了到达这一步需要满足三个条件 :

  1. 至少有一个输入,即argc >= 2,因为此题只取用了argv[1],所以argc = 2即可,也就是只输入一个参数. argc代表输入的参数个数, 程序名字是一个,输入的内容是一个,共两个.
  2. 输入的参数的长度为20个字节
  3. check_password()函数的返回值等于全局变量hashcode = 0x21DD09EC
    前两个条件容易满足,只需要保持有一个输入且长度为20字节即可。
    第三个条件则需要分析check_password(const char * p)函数
  • 第二步 : 分析主要函数check_password()
    可以看到输入的参数argv[1]的指针被传给char指针 p, 然后将char指针p的值强制转换为int型赋给int型指针ip. 那么ip指针所指向的空间的长度为20字节(在满足上述1和2的条件下, 这20字节就是我们输入的字节),也就是5个int型数字(int占4字节), 将5个int型数字相加就是函数的返回值.
unsigned long check_password(const char * p){
  int* ip = (int*) p;
  int i;
  int res = 0;
  for (i = 0; i < 5 ; i++){
    res += ip[i];
  }
  return res;
}

解题的主要目标就可确定为 : 输入20个字节的char字符, 将每4个char字符转换为1个int数字后相加,最终的结果等于0x21DD09EC

解题方法

  • 第一步 : 把0x21DD09EC拆分为5个int型数字, 我拆分为这5个0x1D010101, 0x016D0101, 0x016D0501, 0x01010174, 0x01010175.
  • 第二步, 把这5个数用char类型输出, 以此作为该程序的输入
python -c "print '\x01'*3+'\x1d'+'\x01'*2+'\x6d'+'\x01'*2+'\x05'+'\x6d'+'\x01'+'\x74'+'\x01'*3+'\x75'+'\x01'*3"
//这是python2.7的代码,注意数字的低位在前高位在后是因为主机是小端模式
  • 第三步, 将第二步的输出作为程序col的启动参数, 因为目标主机是linux,所以直接使用linux命令
./col $(python -c "print '\x01'*3+'\x1d'+'\x01'*2+'\x6d'+'\x01'*2+'\x05'+'\x6d'+'\x01'+'\x74'+'\x01'*3+'\x75'+'\x01'*3")

注意 : 输入数字的拆分原则: 不能出现0x00,会被视为分割输入参数的空格,导致输入1个参数的20字节读取后被分割为数个参数. 另外标准ascii码的的范围为0x00~0x7f, 所以分割的字节不能出现大于0x7f的,否则会在python输出字符时出现问题.

基础知识补充

大小端 :是数据存放的方式. 低地址存高位是大端, 低地址存低位是小段. 假设地址从小到大增长, 对于0x123456, 大端存储为 12 34 56, 小端存储为56 34 12
linux命令 :

  • cat : 查看内容
  • ./program $(command): 用./program来执行当前目录下的程序, $()中的command会先被执行,然后将执行的结果, 作为program的输入参数../program (反撇号)command(反撇号). 以后可能会有下面这种形式, 但是|命令是输入到缓冲区, 所以程序需要读缓冲区命令, 而此题是main函数直接传参,所以下面代码不能使用.
python -c "print 'a'*10+'xxx'" | ./program

你可能感兴趣的:([pwnable.kr]第一题fd)