Skip to content

Pwnable kr input

复制本地路径 | 在线编辑

就是考察对C的掌握,很有用。

处理参数

源代码如下

if(argc != 100) return 0;
if(strcmp(argv['A'],"\x00")) return 0;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;

Python 处理

python使用popen / system,代码如下。主要是\x00那么就是空字符串,其他没什么,比较自然。

args = list("A" * 99)
args[ord("A")-1] = ""
args[ord("B")-1] = "\x20\x0a\x0d"

pro = subprocess.Popen(["./input"]+args, stdin = stdinr, stderr = stderrr, env=env)

C 处理

需要注意:
结尾必须赋值为NULL!!

argv[0] = "/home/input2/input";
for(int i=1; i<100; i++) argv[i] = "a";
argv['A'] = "\x00";
argv['B'] = "\x20\x0a\x0d";
argv[100] = NULL;
execve("/home/input2/input", argv, envp);

注意点

  • 没什么好说的,但是在tiny_easy (pwnable kr)中,算是学到一个:
    argv[0] 是可以不为程序名!

标准输入输出

源代码如下,注意一个是read(0),一个是read(2)

char buf[4];
read(0, buf, 4);
if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
read(2, buf, 4);
if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;

Python 处理

stdinr, stdinw = os.pipe()
stderrr, stderrw = os.pipe()
os.write(stdinw, "\x00\x0a\x00\xff")
os.write(stderrw, "\x00\x0a\x02\xff")

C 处理

int pipe_stdin[2] = {-1,-1}, pipe_stderr[2] = {-1, -1};
if(pipe(pipe_stdin) < 0 || pipe(pipe_stderr) < 0) {
    perror("Cannot create pipe!");
    exit(-1);
}

if((pid_child = fork()) < 0) {
    perror("Cannot create child process!");
    exit(-1);
}

if(pid_child == 0) {
    // 子进程先等待父进程重定向,然后关闭不使用的pipe read
    sleep(1);
    close(pipe_stdin[0]);   
    close(pipe_stderr[0]);
    // 父进程此时已经把pipe read 重定向到stdin 和 stderr
    write(pipe_stdin[1], "\x00\x0a\x00\xff", 4);
    write(pipe_stderr[1], "\x00\x0a\x02\xff", 4);
}
else
{
    // 父进程无需pipe write操作,首先close掉,然后把pipe read重定向到0和2
    close(pipe_stdin[1]);
    close(pipe_stderr[1]);
    dup2(pipe_stdin[0], 0);
    dup2(pipe_stderr[0], 2);

    execve("/home/input2/input", argv, envp);
}

环境变量

源代码如下,关键是要知道下面这句话什么意思,什么意思呢,看处理方案就知道了。

if( strcmp( "\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef") ) ) return 0;

Python 处理

env = {"\xde\xad\xbe\xef" : "\xca\xfe\xba\xbe"}

C 处理

char *envp[2] = {"\xde\xad\xbe\xef=\xca\xfe\xba\xbe", NULL};

文件交互

源代码如下,意思是从文件名\x0a读取前4个字节,看是否是\x00\x00\x00\x00

FILE* fp = fopen("\x0a", "r");
if(!fp) return 0;
if( fread(buf, 4, 1, fp)!=1 ) return 0;
if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
fclose(fp);

Python 处理

with open("\x0a","wb") as f:
        f.write("\x00"*4)

C 处理

fp = fopen("\x0a","wb");
if(!fp) {
perror("Cannot open file.");
exit(-1);
}
fwrite("\x00\x00\x00\x00",4,1,fp);
fclose(fp);
fp = NULL;

网络编程

源代码如下,建议先搞懂什么意思。

int sd, cd;
struct sockaddr_in saddr, caddr;
sd = socket(AF_INET, SOCK_STREAM, 0);

if(sd == -1){
        printf("socket error, tell admin\n");
        return 0;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons( atoi(argv['C']) );
if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
        printf("bind error, use another port\n");
        return 1;
}
listen(sd, 1);
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
if(cd < 0){
        printf("accept error, tell admin\n");
        return 0;
}
if( recv(cd, buf, 4, 0) != 4 ) return 0;
if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;

Python 处理

time.sleep(2)
args[ord('C')-1] = "9988" # port
s = socket.socket()
s.connect(("127.0.0.1",9988))
s.send("\xde\xad\xbe\xef")

C 处理

argv['C'] = "55555";
sleep(5);
int sockfd;
struct sockaddr_in saddr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) {
    perror("Cannot create socket!");
    exit(-1);
}

saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(55555);
if(connect(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
    perror("Cannot connect to server!");
    exit(-1);
}
write(sockfd, "\xde\xad\xbe\xef", 4);
close(sockfd);