几道题中的学习

  1. 1. Python
    1. 1.1. Requests
    2. 1.2. exec、eval、represents
    3. 1.3. 执行shell命令
  2. 2. 正则表达式
    1. 2.1. 使用场景
    2. 2.2. 正则的贪婪与非贪婪(惰性)
    3. 2.3. 贪婪与非贪婪
    4. 2.4. 原理浅析
    5. 2.5. 实例
  3. 3. Tmux配置记录

前些天一直在刷题,不过都是一些挺简单的,然后有几道需要python脚本的题可谓是把我弄了一波,认认真真地去学习了一波python以及正则。就聊一下这几道题收获吧。

Python

Requests

首先是python requests库的学习

对于request的回显如果显示乱码的话,可以添加

1
rep.encoding = 'utf-8'

进阶用法可以用

1
r = requests.session()

用来保持会话,以及可以直接实现带cookie二次访问

1
2
3
4
#比如第一次建立链接
rep = r.get('xxx.com')
#第二次需要post数据,以及以上次的cookie访问
rep2 = r.post('xxx.com',data=data)

这就很方便了,不需要再单独记录cookie来确定是同一次session了

还有python的正则库re

1
2
3
4
5
import re
pattern = re.compile(r'^[^=]*')
match = pattern.match(yourString)
if match:
print match.group(0)

在re.compile引号中输入你的正则表达式,然后进行匹配

exec、eval、represents

exec语句用来执行储存在字符串或文件中的Python语句。例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句。

1
exec("print('Hello World')")

运行结果:

Hello World

eval语句用来计算存储在字符串中的有效Python表达式。

1
eval_r("2 * 3")

运行结果:

6

repr函数用来取得对象的规范字符串表示。注意,在大多数时候有eval_r(repr(object)) == object。

可以参考Python中repr与str区别

执行shell命令

  1. os.system

    os模块中的os.system()这个函数来执行shell命令

os.system('ls')

输出结果:

Appalication Desktop Downloads

print os.system('mkdir test')

输出结果:

0

可以看到结果打印出0,表示命令执行成功;否则表示失败(再次执行该命令,输出:子目录或文件 test 已经存在。1)

再次执行:

mkdir: test: File exists

256

注,这个方法得不到shell命令的输出。

  1. popen()

    这个方法能得到命令执行后的结果是一个字符串,要自行处理才能得到想要的信息。

    1
    2
    3
    4
    5
    import os
    str = os.popen("ls").read()
    a = str.split("\n")
    for b in a:
    print b

    输出结果与os.system('ls')一致

  2. commands模块

    可以很方便的取得命令的输出(包括标准和错误输出)和执行状态位

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import commands
    a,b = commands.getstatusoutput('ls')
    a是退出状态
    b是输出的结果。
    >>> import commands
    >>> a,b = commands.getstatusoutput('ls')
    >>> print a
    0
    >>> print b
    Application
    Desktop
    Downloads

    commands.getstatusoutput(cmd)返回(status,output)

    commands.getoutput(cmd)只返回输出结果

    commands.getstatus(file)返回ls -ld file 的执行结果字符串,调用了getoutput,不建议使用这个方法。

  3. subprocess模块

    使用subprocess模块可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态。使用subprocess模块的目的是替代os.system()、os.popen()、commands.等旧的函数或模块。

    1
    2
    3
    4
    5
    6
    7
    import subprocess
    subprocess.call(command, shell=True)
    #会直接打印出结果。
    subprocess.Popen(command, shell=True)
    #也可以是subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) 这样就可以输出结果了。
    #如果command不是一个可执行文件,shell=True是不可省略的。
    #shell=True意思是shell下执行command

正则表达式

正则表达式自己还是有点弱,主要是一些原理自己有点懒得去了解,就导致每次写正则自己都很蠢…

转载改编自:正则表达式 - 贪婪与非贪婪(惰性)(侵删)

使用场景

有时,我们想用正则匹配以某个子串开头,且以某个子串或字符结尾的子字符串,但是结尾的字串或字符在原字符串中出现了多次,但我们只想匹配从开始处到第一次出现的地方,换句话说,想得到开始和结尾之间内容最少的匹配

正则的贪婪与非贪婪(惰性)

通常使用如下字符类描述前导字符的重复特征:

  1. ?: 告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。

  2. +: 告诉引擎匹配前导字符1次或多次。

  3. *: 告诉引擎匹配前导字符0次或多次。

  4. {min, max}: 告诉引擎匹配前导字符min次到max次。min和max都是非负整数。如果有逗号而max被省略了,则表示max没有限制;如果逗号和max都被省略了,则表示重复min次。
    因此 {0,} 和 * 一样,{1,} 和 + 的作用一样。

贪婪与非贪婪

贪婪 : 默认情况下,? + * {min, max}都是贪婪的,也就是说,它会根据前导字符去匹配尽可能多的内容。

非贪婪(惰性) : 非贪婪就是匹配尽可能少的内容。

原理浅析

结合实例来分析哈基于正则的引擎对文本的匹配过程。原始字符串:This is a <EM>first</EM> test,使用正则<.+>来匹配HTML标签,期望第一次匹配得到<EM>,第二次匹配得到</EM>,实际却是第一次匹配就得到了<EM>first</EM>

来看看匹配过程,第一个记号是<,这是一个文本字符,匹配其自身。第二个符号是.,匹配了字符E,然后+一直可以匹配其余的字符,直到一行的结束。然后到了换行符,匹配失败(.不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配,即试图匹配>。到目前为止,<.+已经匹配了<EM>first</EM> test。引擎会试图将>与换行符进行匹配,结果失败了。于是引擎进行回溯。回溯后的匹配状况是 <.+ 匹配 <EM>first</EM> tes。于是引擎将>t进行匹配。显然还是会失败。这个过程继续,直到 <.+ 匹配 <EM>first</EM>>匹配。于是引擎找到了一个匹配<EM>first</EM>。记住,正则导向的引擎是急切的,所以它会急着报告它找到的第一个匹配。而不是继续回溯,即使可能会有更好的匹配,例如<EM>。所以我们可以看到,由于+的贪婪性,使得正则表达式引擎返回了一个最左边的最长的匹配。

如果想得到期望的结果,就需要启用非贪婪模式:<.+?>

总结:如果是贪婪匹配模式,正则引擎会一直匹配到字符串最后;当匹配为false时,就回溯以找到倒数第一个匹配位置,返回匹配结果。 如果是非贪婪匹配模式,正则引擎会匹配到符合pattern的末尾位置那个字符,然后再往后走一步,发现匹配为false时,就回溯以找到最近一个匹配为true的位置,返回匹配结果。

实例

例如,原始字符串:

1
{"accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"},"dbGrant":{"0000031736":"READWRITE"},"dbSchemaId":"0000031737"}

现在想把这部分敏感信息替换为空字符串:

1
"accesskey":{"acccessKeyId":"XhUURxsMlJE6EiXf","accessKeySecret":"Q9fMpgBgRnKycMRD28MMkkFMbiNkbY"},

先不考虑结尾的逗号,尝试正则:"accesskey":\{.+\},直接匹配至原始字符串结尾的}字符,因为引擎默认会匹配尽可能多的内容。

考虑到贪婪性,将正则修改为:"accesskey":\{.+\}+?,匹配结果一样。纳尼?难道我对贪婪性的理解有问题。梳理哈使用姿势,我期望它匹配到开始位置之后出现的第一个}字符,对应的表达式部分为}+?。套用非贪婪模式分析问题,期望对一个或多个}字符进行匹配,且匹配尽可能少的内容,但在原始串中,}字符都是分开的,没有连续,无论如何只能匹配一个单独的}字符。可见对}字符开启非贪婪模式匹配行不通。

想要匹配到开始位置之后出现的第一个}字符 也可以表达为 开始位置和末尾}字符之间的内容最少,对应正则部分修改为:.+?,完整表达式:"accesskey":\{.+?\},测试匹配结果,妥妥的。

以上均为转载,这里讲讲自己的实例

1
sid=14d8f776-a969-4252-b35a-f83a807e7f2d;userName=111111111;

目的是匹配

1
sid=14d8f776-a969-4252-b35a-f83a807e7f2d;

一开始自己瞎糊弄了半天,最后找到了比较接近的sid=.*;,可是这个直接匹配到了行末,把userName一起包含进去了,这时候就要考虑到非贪婪性了,即sid=.*?;就可以匹配到第一个遇到的;

又如

1
1087080534*1062477688-245892309-863670697+1430950488-2128604487+787613783-929770459-331572804*1754549713+81041939=?;

匹配前面的算数表达式(=前面的表达式不包括=

自己也瞎糊弄了好久,一开始写的是.*=死活都包含了=,这就很烦了

然后认真去看了正则,用了[^],解释是

Match any character that is not in the set.

就是匹配任何不包含这个字符的字符串

所以最后是^[^=]*

还有对于

1
跑的还不错,给你flag吧: NzI3NTY3

匹配最后的base64字符串,之前考虑的是(?=:).*

但是还是老问题老是匹配了:?<在python中不能用…这就比较麻烦了

然后查了一下发现可以用group来弄,差不多就是给他们分组的意思

1
(.*)(: )(.*)

这就分成了三组,第一组匹配的是中文,第二组匹配的是:,第三组匹配的就是最后的字符串,所以我们只需要提取group(3)就好了。

Tmux配置记录

详情参考tmux配置

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
#-- base --#
set -g default-terminal "screen-256color"
set -g display-time 3000
set -g history-limit 10000
set -g base-index 1
set -g pane-base-index 1
set -s escape-time 0
set -g mouse on
#-- bindkeys --#
# split windows like vim. - Note: vim's definition of a horizontal/vertical split is reversed from tmux's
unbind s
bind s split-window -v
bind S split-window -v -l 40
bind v split-window -h
bind V split-window -h -l 120
# navigate panes with hjkl
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# key bindings for horizontal and vertical panes
unbind %
bind | split-window -h # 使用|竖屏,方便分屏
unbind '"'
bind - split-window -v # 使用-横屏,方便分屏
# swap panes
bind ^u swapp -U
bind ^d swapp -D
bind q killp
bind ^e last
unbind r
bind r source-file ~/.tmux.conf \; display "Configuration Reloaded!"
#-- statusbar --#
set -g status-justify centre
set -g status-left "#[fg=red]s#S:w#I.p#P#[default]"
set -g status-right '[#(whoami)#(date +" %m-%d %H:%M ")]'
set -g status-left-attr bright
set -g status-left-length 120
set -g status-right-length 120
set -g status-utf8 on
set -g status-interval 1
set -g visual-activity on
setw -g monitor-activity on
setw -g automatic-rename off
# default statusbar colors
set -g status-bg colour235 #base02
set -g status-fg colour136 #yellow
set -g status-attr default
# default window title colors
setw -g window-status-fg colour244
setw -g window-status-bg default
#setw -g window-status-attr dim
# active window title colors
setw -g window-status-current-fg colour166 #orange
setw -g window-status-current-bg default
#setw -g window-status-current-attr bright
# window title string (uses statusbar variables)
set -g set-titles-string '#T'
set -g status-justify "centre"
set -g window-status-format '#I #W'
set -g window-status-current-format ' #I #W '
# pane border
set -g pane-active-border-fg '#55ff55'
set -g pane-border-fg '#555555'
# message text
set -g message-bg colour235 #base02
set -g message-fg colour166 #orange
# pane number display
set -g display-panes-active-colour colour33 #blue
set -g display-panes-colour colour166 #orange
# clock
setw -g clock-mode-colour colour64 #green
# 修改进入命令模式按键
# remap prefix to Control + a
# set -g prefix C-a
# unbind C-b
# bind C-a send-prefix


Article Author: Zeddy

Article Link: https://blog.zeddyu.info/2018/04/13/%E5%87%A0%E9%81%93%E9%A2%98%E4%B8%AD%E7%9A%84%E5%AD%A6%E4%B9%A0/index.html

Copyright Notice: With the exception of the special statement at the beginning of the article, all articles can be reprinted in accordance with the CC BY 4.0 agreement with the author's permission.

记一道比较简单的上传绕过 HGame部分writeup

Comments