从pwnable.kr入门pwn(1) input

dr003   ·   发表于 2021-02-03 21:45:20   ·   CTF&WP专版

pwnable.kr input

ssh 远程连接
cat input.c

关键语句分析及函数学习

1.

  • argv argument value 指针数组,用来存放指向你的字符串参数的指针,每一个元素指向一个参数
  • argc argument counter 参数个数
    argv本身是指针数组 argv[0] 保存路径 argv[1~argc-1] 指向参数
    argv[argc]=NULL

(1)argc=100 要初始化101个告诉他哪里结束 也就是到argv[100]=NULL
(2)argv[‘A’] 原本 argv[n] n应该是数字 所以这里取ascii码

2.

(1)函数原型ssize_t read(int fd, void *buf, size_t count);

  • ①buf是指针型 也就是位置 所以char buf[4] buf本身是字符型数组 不加下标当作指针用 也就是充当缓存区
  • ② 4就是count 取几个字节 如果是中文一个算两个
  • ③ fd原本是STDIN_FILENO接收键盘的输入STDOUT_FILENO:向屏幕输出
    这里0/1/2 是文件描述符
    0是输入 1是输出 2是报错
    0:STDIN_FILENO 1:STDOUT_FILENO 2:STDERR_FILENO
    (2)函数原型int memcmp(const void str1, const void str2, size_t n));
    比较str1 str2 前n个字节 >返回 1 = 返回0 < 返回-1
    赋值使相等

3.

(1)getenv() 获取环境变量 也就是名字是deadbeef的变量

使得值是cafebabe

4.

  • (1)函数原型FILE fopen(const char path,const char * mode);
    path 路径 mode 权限 wb和w在Linux下一样
    要使fp存在 则需要有文件且能打开
  • (2)函数原型size_t fread(void buffer,size_t size,size_t count, FILE stream)

buffer读取存放位置 size每次读取大小 count读取次数 stream 文件流 读取对象

5.


if部分都是确定成功就不会报错

函数原型int recv(SOCKETs, charFAR* buf, int len, int flags);

  • 第一个参数指定接收端套接字描述符;
  • 第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
  • 第三个参数指明buf的长度;
  • 第四个参数一般置0。

通常recv有几种返回值

  • 1.==0
    表示收到FIN包, 因为FIN包,是状态为标记为FIN的空包,没有携带数据,所以recv的长度为0
  • 2.>0
    表示收到了数据, 但是有没有收完,是不知道的
  • 3.<0
    == EAGAIN 表示接收缓冲区中已经没数据了,需要暂停下,业务程序需要检查下包的完整性,才知道有没有收完,如果没收完,就继续recv
    != EAGAIN 表示接收出错了,如果是服务端, 就可以直接关闭连接了.|||摘自https://www.cnblogs.com/ctrlzhang/p/5421297.html
    也就是说接收4个字节且为deadbeef
    建立连接 发送数据为deadbeef

    源码分析完毕接下来是写exp

    先确认思路要干什么

  • 1.argv[0] 路径 argv[‘A’] \x00 argv[‘B’] \x20\x0a\x0d argv[100] NULL argv[‘C’] port (在网络连接那里用)
  • 2.从标准错误流输入\x00\x0a\x02\xff,从标准输入流输入\x00\x0a\x00\xff
  • 3.环境变量 \xde\xad\be\ef=\xca\xfe\xba\xbe
  • 4.写文件内容是\x00\x00\x00\x00 路径\x0a
  • 5.网络连接 传输\xde\xad\xbe\xef

代码(井号会触发格式所以这里没写)

  1. include <stdio.h>
  2. include <unistd.h>
  3. include <sys/types.h>
  4. include <stdlib.h>
  5. include <sys/wait.h>
  6. include <arpa/inet.h>
  7. include <sys/socket.h>
  8. include <netinet/in.h>
  9. int main()
  10. {
  11. char *argv[101]={"/home/input2", [1 ... 99] = "A", NULL};
  12. argv['A']="\x00";
  13. argv['B']="\x20\x0a\x0d";
  14. argv['C']="55555";//1
  15. {建立管道pipe实现读写
  16. pipe是进程之间交互
  17. int pipe2stdin[2]={-1,-1};//0是读取 1是输入
  18. int pipe2stderr[2]={-1,-1};
  19. pid_t childpid;
  20. pipe(pipe2stdin);
  21. pipe(pipe2stderr);
  22. if ( childpid == 0 ){
  23. close(pipe2stdin[0]); close(pipe2stderr[0]);
  24. //环境配置
  25. write(pipe2stdin[1],"\x00\x0a\x00\xff",4);
  26. write(pipe2stderr[1],"\x00\x0a\x02\xff",4);//2
  27. else {
  28. /* Parent process */
  29. close(pipe2stdin[1]); close(pipe2stderr[1]);
  30. dup2(pipe2stdin[0],0); dup2(pipe2stderr[0],2);//相当于read
  31. char *env[2] = {"\xde\xad\xbe\xef=\xca\xfe\xba\xbe", NULL};
  32. execve("/home/input2/input",argv,env); //3
  33. //execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。
  34. }
  35. FILE* fp = fopen("\x0a","w");
  36. fwrite("\x00\x00\x00\x00",4,1,fp);
  37. fclose(fp);//4
  38. 需要网络连接
  39. int sockfd;
  40. struct sockaddr_in server;
  41. sockfd = socket(AF_INET,SOCK_STREAM,0);//建立socket
  42. if ( sockfd < 0){//建立socket
  43. perror("Cannot create the socket");
  44. exit(1);
  45. }
  46. my_addr.sin_family=AF_INET;//该属性表示接收本机或其他机器传输
  47. my_addr.sin_port=htons(PORT);//端口号
  48. my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//IP
  49. if ( connect(sockfd, (struct sockaddr*) &server, sizeof(server)) < 0 ){//绑定地址结构体和socket
  50. perror("Problem connecting");
  51. exit(1);
  52. }
  53. //环境配置
  54. char buf[4] = "\xde\xad\xbe\xef";
  55. write(sockfd,buf,4);
  56. close(sockfd);//5
  57. }
用户名金币积分时间理由
veek 50.00 0 2021-02-05 11:11:29 感谢分享~

打赏我,让我更有动力~

0 条回复   |  直到 2021-2-4 | 986 次浏览
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.