pwnable.kr之input
连接到远程服务器:ssh input2@pwnable.kr -p2222
查看题目所给的代码,根据题目的要求我们要给出所有符合条件的输入才能拿到flag,本来想在输入上动点歪脑筋,结果输入有字节数的限制,然后再查看一下程序是否有保护
Arch: amd64--little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
发现有栈溢出和数据执行保护,就绝了走捷径的心思。
查看代码知道有五步要走,为了检测每步是否正确,使用命令:scp -P 2222 input2@pwnable.kr:/home/input2/input /home/countfatcode/Code 把input文件下载到本地。
scp命令详解请看:https://blog.csdn.net/sanbingyutuoniao123/article/details/72420637
第一部分:argv
// argv
if(argc != ) return ;
if(strcmp(argv['A'],"\x00")) return ;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return ;
printf("Stage 1 clear!\n");
因为要传入的参数过多,可以用 execve() 函数来实现。
函数详解请看:https://www.cnblogs.com/jxhd1/p/6706701.html
于是可以构造c语言代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *argv[]={"input",[ ... ]="A",NULL};
argv['A']="\x00";
argv['B']="\x20\x0a\x0d";
execve("input",argv,NULL);
return ;
}
编译运行,得到结果:
Welcome to pwnable.kr
Let's see if you know how to give input to program
Just give me correct inputs then you will get the flag :)
Stage clear!
第二部分:stdio
查看代码:
// stdio
char buf[];
read(, buf, );
if(memcmp(buf, "\x00\x0a\x00\xff", ))
return ;
read(, buf, );
if(memcmp(buf, "\x00\x0a\x02\xff", ))
return ;
printf("Stage 2 clear!\n");
第一个 read() 函数的文件描述符是0,表示从终端读入字符,第二个 read() 函数的文件描述符是 2,表示从标准错误输出读入字符,此时就要用到 pipe管道来解决。
pipe详解:https://blog.csdn.net/skyroben/article/details/71513385
因为有两个read,所以要创建两个管道,代码如下:
int fd1[],fd2[];
int ret1,ret2; //用来接受pipe函数的返回值
ret1=pipe(fd1);
if(ret1==-)
{
perror("pipe fd1 error:");
exit();
}
ret2=pipe(fd2);
if(ret2==-)
{
perror("pipe fd2 error:");
exit();
}
再用 fork() 创建子进程,代码如下:
pid_t id=fork()
第二部分完整代码如下:
//stdio
int fd1[],fd2[];
int ret1,ret2; //用来接受pipe函数的返回值
ret1=pipe(fd1);
if(ret1==-)
{
perror("pipe fd1 error:");
exit();
}
ret2=pipe(fd2);
if(ret2==-)
{
perror("pipe fd2 error:");
exit();
}
pid_t id=fork();
if(id==) //子进程
{
close(fd1[]);
close(fd2[]); //关闭子进程读端
write(fd1[],"\x00\x0a\x00\xff",);
write(fd2[],"\x00\x0a\x02\xff",);
}
else //父进程
{
close(fd1[]);
close(fd2[]);
dup2(fd1[],);
dup2(fd2[],);//文件描述符重定向
close(fd1[]);
close(fd2[]); //env
char *env[]={"\xde\xad\xbe\xef=\xca\xfe\xba\xbe",NULL}; //file
FILE *fp=fopen("\x0a","w");
if(fp==NULL)
printf("文件打开失败\n");
else
{
fwrite("\x00\x00\x00\x00",,,fp);
fclose(fp);
execve("input",argv,env);
}
}
将一二部分的代码结合起来运行一下,发现正确。
第三部分:env
查看代码:
// env
if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return ;
printf("Stage 3 clear!\n");
getenv() 函数的作用是获取环境变量名为 \xde\xad\xbe\xef 的变量值,这时就要用 execve() 的第三个参数来构造该环境变量,具体代码如下:
//env
char *env[]={"\xde\xad\xbe\xef=\xca\xfe\xba\xbe",NULL};
结合一二部分的代码运行,发现正确。
第四部分:file
查看代码:
// file
FILE* fp = fopen("\x0a", "r");
if(!fp) return ;
if( fread(buf, , , fp)!= ) return ;
if( memcmp(buf, "\x00\x00\x00\x00", ) ) return ;
fclose(fp);
printf("Stage 4 clear!\n");
这部分是关于文件操作,具体代码如下:
//file
FILE *fp=fopen("\x0a","w");
if(fp==NULL)
printf("文件打开失败\n");
else
{
fwrite("\x00\x00\x00\x00",,,fp);
fclose(fp);
execve("input",argv,env);
}
再结合第一二三部分的代码运行,正确。
第五部分:network
第五题主要涉及的是socket编程,题目给的代码是:
// network
int sd, cd;
struct sockaddr_in saddr, caddr;
sd = socket(AF_INET, SOCK_STREAM, );
if(sd == -){
printf("socket error, tell admin\n");
return ;
}
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)) < ){
printf("bind error, use another port\n");
return ;
}
listen(sd, );
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
if(cd < ){
printf("accept error, tell admin\n");
return ;
}
if( recv(cd, buf, , ) != ) return ;
if(memcmp(buf, "\xde\xad\xbe\xef", )) return ;
printf("Stage 5 clear!\n"); // here's your flag
system("/bin/cat flag");
观察知题目提供的是服务器端的代码,所以我们要通过编程实现客户端的代码
sleep();
struct sockaddr_in server;
int sockfd = socket(AF_INET,SOCK_STREAM,); //创造一个套字节,客户端只有一个套字节
if(sockfd<) //检查是否创造成功
{
perror("Cannot create the socket:");
exit();
}
server.sin_family=AF_INET; //使用IPv4地址
server.sin_addr.s_addr=inet_addr("127.0.0.1"); //具体的IP地址
server.sin_port=htons(); //端口
if(connect(sockfd,(struct sockaddr*)&server,sizeof(server))<)
{
perror("Problem connecting");
exit();
}
printf("Connected\n");
char buf[]="\xde\xad\xbe\xef";
write(sockfd,buf,);
close(sockfd);
return ;
最后这题完整的代码如下:
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//argv
char *argv[]={"./input",[ ... ]="A",'\0'};
argv['A']="\x00";
argv['B']="\x20\x0a\x0d";
argv['C']=""; //stdio
int fd1[],fd2[];
int ret1,ret2; //用来接受pipe函数的返回值
ret1=pipe(fd1);
if(ret1==-)
{
perror("pipe fd1 error:");
exit();
}
ret2=pipe(fd2);
if(ret2==-)
{
perror("pipe fd2 error:");
exit();
}
pid_t id=fork();
if(id==) //子进程
{
close(fd1[]);
close(fd2[]); //关闭子进程读端
write(fd1[],"\x00\x0a\x00\xff",);
write(fd2[],"\x00\x0a\x02\xff",);
}
else //父进程
{
close(fd1[]);
close(fd2[]);
dup2(fd1[],);
dup2(fd2[],);//文件描述符重定向
close(fd1[]);
close(fd2[]); //env
char *env[]={"\xde\xad\xbe\xef=\xca\xfe\xba\xbe",NULL}; //file
FILE *fp=fopen("\x0a","w");
if(fp==NULL)
printf("文件打开失败\n");
else
{
fwrite("\x00\x00\x00\x00",,,fp);
fclose(fp);
execve("input",argv,env);
}
}
//network
sleep();
struct sockaddr_in server;
int sockfd = socket(AF_INET,SOCK_STREAM,);
if(sockfd<)
{
perror("Cannot create the socket:");
exit();
}
server.sin_family=AF_INET;
server.sin_addr.s_addr=inet_addr("127.0.0.1");
server.sin_port=htons();
if(connect(sockfd,(struct sockaddr*)&server,sizeof(server))<)
{
perror("Problem connecting");
exit();
}
printf("Connected\n");
char buf[]="\xde\xad\xbe\xef";
write(sockfd,buf,);
close(sockfd);
return ;
}
注意:我们需要用scp命令把代码文件上传到服务器的tmp文件夹,由于tmp文件夹里没有flag文件,还需要用ln命令进行连接,最后编译运行就可以得到flag。
pwnable.kr之input的更多相关文章
- 【pwnable.kr】input
这道题是一道一遍一遍满足程序需求的题. 网上其他的题解都是用了C语言或者python语言的本地调用,我想联系一下pwntools的远程调用就写了下面的脚本, 执行效果可以通过1~4的检测,到最后soc ...
- pwnable.kr详细通关秘籍(二)
i春秋作家:W1ngs 原文来自:pwnable.kr详细通关秘籍(二) 0x00 input 首先看一下代码: 可以看到程序总共有五步,全部都满足了才可以得到flag,那我们就一步一步来看 这道题考 ...
- 【pwnable.kr】 [simple login]
Download : http://pwnable.kr/bin/login Running at : nc pwnable.kr 9003 先看看ida里面的逻辑. 比较重要的信息时input变量再 ...
- 【pwnable.kr】 mistake
又一道pwnable,我还没放弃.. ssh mistake@pwnable.kr -p2222 (pw:guest) 源代码如下: #include <stdio.h> #include ...
- 【pwnable.kr】fb
这是pwnable.kr的签到题,记录pwn入门到放弃的第一篇. ssh fd@pwnable.kr -p2222 (pw:guest) 题目很简单,登录上了ssh后,发现了3个文件:fd,fd.c, ...
- pwnable.kr之simple Login
pwnable.kr之simple Login 懒了几天,一边看malloc.c的源码,一边看华庭的PDF.今天佛系做题,到pwnable.kr上打开了simple Login这道题,但是这道题个人觉 ...
- pwnable.kr的passcode
前段时间找到一个练习pwn的网站,pwnable.kr 这里记录其中的passcode的做题过程,给自己加深印象. 废话不多说了,看一下题目, 看到题目,就ssh连接进去,就看到三个文件如下 看了一下 ...
- pwnable.kr bof之write up
这一题与前两题不同,用到了静态调试工具ida 首先题中给出了源码: #include <stdio.h> #include <string.h> #include <st ...
- pwnable.kr col之write up
Daddy told me about cool MD5 hash collision today. I wanna do something like that too! ssh col@pwnab ...
随机推荐
- 精讲RestTemplate第6篇-文件上传下载与大文件流式下载
本文是精讲RestTemplate第6篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- Spring,SpringMVC,MyBatis,Hibernate,Servlet的生命周期,jsp有哪些内置对象,Tomcat,Cookie和Session的作用以及区别,oracle,MYSQL等面试题总结
1. 什么是Spring,谈谈你对Spring的理解 Spring是我们JAVA开发人员在搭建后台时选用的一个轻量级的开源框架,Spring框架目前也是功能丰富,十分优秀企业级采用最多的一个框架. S ...
- 生成kafka内部请求与响应的接口文档
生成kafka内部请求与响应的接口文档 /** */ package com.code260.ss.kafka10demo; import java.io.File; import java.io.I ...
- 基于Prometheus和Grafana打造业务监控看板
前言 业务监控对许许多多的场景都是十分有意义,业务监控看板可以让我们比较直观的看到当前业务的实时情况,然后运营人员可以根据这些情况及时对业务进行调整操作,避免业务出现大问题. 老黄曾经遇到过一次比较尴 ...
- MyBatis学习-使用Druid连接池将Maybatis整合到spring
目录 前言 什么是Druid连接池 Druid可以做什么? 导入库包 连接oracle 连接mysql 导入mybatis 导入druid 导入spring-jdbc包 导入spring包 导入spr ...
- JavaScript 空间坐标
基础知识 首先参考画布分为视口(窗口)与文档的含义 网页很多都是多屏,所以文档尺寸一般大于视口尺寸 视口尺寸不包括浏览器工具条.菜单.标签.状态栏等 当打开控制台后,视口尺寸相应变小 文档像posit ...
- ES6中的变量的解构赋值, 解放我们的双手,实现变量的批量赋值
ES6--变量的解构赋值 引言 正文 一.数组的解构赋值 解构失败 不完全解构 默认值 二.对象的解构赋值 三.字符串的解构赋值 结束语 引言 变量的解构赋值, 听起来很复杂, 简单点说可以理解成批量 ...
- Java之Annotation(注解)——注解处理器
如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...
- vant官网无法打开,这里教你解决
是否大家和我一样,vant-weapp官网突然打不开了 像这样: 但我发现在码云上有一个国内的版本 https://vant-contrib.gitee.io/vant/#/zh-CN/home, ...
- Excel提取身份证出生日期②
问题场景 从user表中的身份信息中提取用户的出生日期: 以下方法也可适用于提取其他数据,不仅是身份证信息: 以下图中数据都为测试数据,不具备真实性! 场景一 user表中的18位身份证,提取出生日期 ...