Rapid Typing & fd in pwnable & col

Rapid Typing& fd in pwnable & col

—– Rapid Typing—–

参考:


分析:

思路参考calulator,不同点在本题所需输入的内容为svg图片,
svg部分截取: Imgur
解码后:Imgur
可见它的代码是xy的二维坐标,将svg图片代码段截取后,转为png图片后,可见,即为我们所求输入内容。
按照x坐标排列后,可见>a-z 0-9< 内即为所求,按正则匹配:
Imgur
再匹配去掉>< 化为字符串即可:
Imgur
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<le> import requests
import base64
import re
r = requests.get('http://123.207.149.64:23331/captcha/')
> soup = BeautifulSoup(r.text,'lxml')
p = soup.find(name='img')
q = str(p)
s= q[36:-4] #把svg代码部分截出
lens = len(s)
lenx = lens - (lens % 4 if lens % 4 else 4)
try:
result = base64.decodestring(s[:lenx])
except:
pass #10-15是解决base64解码直接decode出现的 TypeError: Incorrect padding错误 注:https://blog.csdn.net/lisai17/article/details/21091791
anwser = BeautifulSoup(result,'lxml')
a = anwser.find_all(name='text')
b = sorted(a,key=lambda x:int(x.get('x'))) #对text内容以x大小为序排列
c = '>\w<' #正则匹配出所有特定字符
d = re.findall(c,str(b)) #注意正则匹配模式串还有要匹配的串必须是字符串类型,用str转换
g = re.findall('\w',str(d))
h = ''.join(g) #把列表转化为字符串
print h
r = requests.get ('http://123.207.149.64:23331/captcha/?code='+h, cookies=r.cookies)
print r.text`


—–fd—–

参考:

  • read函数 :ssize_t read(int fd,void * buf ,size_t count);
    read()会把参数fd所指的文件传送nbyte个字节到buf指针所指的内存中。若参数nbyte为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或无可读取的数据。错误返回-1,并将根据不同的错误原因适当的设置错误码。
  • atoi函数:atoi() 函数用来将字符串转换成整数(int),其原型为:int atoi (const char * str);【函数说明】atoi() 函数会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过isspace()函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(‘\0’)才结束转换,并将结果返回。【返回值】返回转换后的整型数;如果 str 不能转换成 int 或者 str 为空字符串,那么将返回 0。

  • arec,argv[] int main(int argc,char *argv[]);第一个参数argc用来存放命令行参数的个数;第二个参数argv是指针数组,它是用来存放命令行中各个参数和命令字的字符串的。关于相关输入:要在执行文件语句后直接加赋值。

    例:https://blog.csdn.net/Eastmount/article/details/20413773


分析:

通过所给远程端口获取题目,ls后,有fd(ELF) ,fd.c ,flag三文件,fd为fd.c编译。尝试打开flag 没有权限 打开fd.c查看源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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 number\n");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;

}

我们希望执行system("/bin/cat flag"); 故需执行!strcmp("LETMEWIN\n", buf),即令buf=LETMEWIN
看到read(fd,buf,32),由read函数的定义,需要使fd==0,即标准输入 故fd=0x1234=4660
输入./fd 4660后可进行输入,输入LETMEWIN,得flag


—–col—–

参考:

  • hash collision 就是针对哈希函数的特性,精心构造数据,使所有数据的哈希值相同,当这些数据保存到哈希表中,哈希表就会退化为单链表,哈希表的各种操作的时间复杂度提升一个数量级,因此会消耗大量CPU资源,导致系统无法快速响应请求,从而达到拒绝服务攻击(Dos)的目的。 本题就是构造与所给hashcode相同的值

    注:https://www.kawabangga.com/posts/2493 http://vearne.cc/archives/34477

  • 《深入理解计算机系统》2.1.4节,大部分机器存储对象以小端法存储.
  • 关于输入,使用了shell语言中的反括号,反引号在Linux shell命令行中有特殊的含义:反引号间的内容,会被shell先执行。其输出被放入主命令后,主命令再被执行

    注:https://www.jianshu.com/p/ed41f2e48464


分析

与fd相似,按所给进行远程连接后,打开col.c分析 源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}

int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}

if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}

首先定义了函数check_password,作用是将p(char类型,1字节),强制转化为int型(4字节)再赋给ip,循环5次相加后得到一个20字节的数
再看main函数部分后,得知当传入的参数经check_password后与所给的hashcode相同时 获得flag,所以20个字节的char p会被分成5段,一段4个字节,
就是我们找5个数相加为0x21DD09EC即可。
我先将0x21DD09EC转为10进制数后,随便找了一个数(123456789)*4后,相减得到最后一个数(16进制:0x46DD598)。
另外注意在输入时使用小端输入。 输入为:

1
./col '0x75BCD15'*4+'0X46DD598'

但是在直接输入了后依然不对,最后找到原因是shell不能直接识别这样的输入,需要写shell语言格式或利用其他语言传参。用其它语言用反括号隔开
正确输入为:

1
./col `python -c "print '\x15\xcd\x5b\x07' * 4 + '\x98\xd5\x6d\x04'"`