ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于tools编写的一些随笔

2021-04-05 14:35:16  阅读:163  来源: 互联网

标签:url os self command tk 编写 随笔 tools def


在实际渗透中,我一直坚信一个思想,如果目标能够渗透进去,而我却没有成功,一定是信息收集的时候,没有收集到关键点。
本文只是一个引子,希望各位师傅们可以有所收获
我们平常少不了的收集手段是端口和目录。而端口我们可以用fofa或者nmap等这些已经灰常好的工具,让我们进行探测。
本文用于一个demo测试,表哥们可以自行改编
本文demo包括:
命令行下工具以及GUI工具,最后介绍一下B/S架构的思考
本人还在学习,所以代码有点菜比,思路最重要,嘤嘤嘤~
让我们早点摆脱脚本小子和ctrl+c ctrl+v工程师的名衔
首先,编写一个工具或者程序首先要有一个思想。
什么是目录探测呢?
第一,要发送请求是不是。
第二,我们要判断响应码是不是200。
第三,可能由于waf的存在,目录不存在响应码也是200,那我们是不是可以在目标站随便输入一个目录,故意让他报错,看他存在的报错信息,是什么,是"页面不存在,跳转"这种字符提示信息。还是提示404。那样是不是我们可以直接在源代码中匹配这些关键词,如果匹配成功我们就判断这个目录不存在。(简单的绕过技巧思路)
那下面我们开始一步一步分析
import requests
a="https://www.baidu.com"
ret=requests.get(a)
if ret.status_code==200:
print("页面存在"+"响应码:"+str(ret.status_code))
else:
print("不存在")
在Python中我们可以用requests包去发送请求判断响应吗是不是200,如果是我们就判断它页面存在
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://www.baidu.com"
resp, err := http.Get(url)
/http.Get 是创建HTTP请求的函数,
如果请求没有出错,resp这个结构体中会得到访问的请求
结果
/
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
//简单一点,可以直接Println("错误")
//把格式字符串输出到指定文件设备中,所以参数比printf多一个文件指针FILE

//os.Stderr用于显示错误信息,大多情况下等用于os.Stdout
}
b, err := ioutil.ReadAll(resp.Body)
cunhuo := resp.StatusCode
defer resp.Body.Close()
/

关键字 defer 用于注册延迟调用。
这些些调用直到 return 前才被执。因此,可以用来做资源清理。
resp.Body字段
包括一个可读的服务器响应流
ioutil.ReadAll函数
从response中读取到全部内容

resp.Body.Close()
关闭resp Boby流

*/
if err != nil {
    fmt.Println("Error!")
    os.Exit(1)
}
if cunhuo == 200 {
    fmt.Println(cunhuo)
    fmt.Println("存在此页面")
} else {
    fmt.Println("不存在此页面")
}
fmt.Printf("%s", b)

}
同样在Go语言内置包中"io/ioutil". "net/http"也提供了相应的方法来进行判断
提醒:根据Go包中规则,只有大写字母才能被引用,所以我们平常会一直看到大写字母开头的引用
if err != nil相当于Python中的try语句(异常处理机制)
我们现在可以得到一个响应码了,但我们正常的思路是在一个..../x(随机变量)这种方式,去循环请求服务器,不断的改变x的值,去查看什么情况下能够得到200的响应码
这时候我们便需要一个打开一个文件(这个文件作为我们的x的值)
在Python我们只需要写一个循环去请求字典中的值,然后写一个判断便可以了
import requests
a="http://220.249.52.134:49872/"
with open("1.txt","r") as f :
b=f.read().splitlines()
for i in b:
rep=requests.get(a+str(i))
if rep.status_code == 200:
print("存在此页面:"+a+str(i))
else:
print(a+str(i)+"不存在")
而在Go语言中我们同样使用此种思路,读取文件去循环发送请求
package main
import (
"bufio"
"fmt"
"net/http"
"os"
)
func main() {
//author yanmu
url := "http://220.249.52.134:49872/"
file, err := os.Open("1.txt")
//os包是系统标准库里面有操作系统相关的函数和变量,打开一个文件可以使用os.open
if err != nil {
fmt.Printf("文件读书失败")
}
defer func() {
file.Close()
}()
//定义一个立即执行的匿名函数
n := bufio.NewScanner(file)
/*
函数NewScanner返回一个Scanner结构体,这个返回值来自于函数参数file

*/
//fmt.Printf("%T-%d\n"m, n, n)
for n.Scan() {
    //n.Scan()相当于其他语言的迭代器iterator,并把迭代器指向的数据存放到新的缓冲区里。新的缓冲区可以用n.Text()得到
    //n.Scan()每一次调用都会调入一个新行,并且会自动将其行末的换行符去掉
    //n.Scan()是一个bool类型,在这里为true
    data := n.Text()
    resp, err := http.Get(url + data)
    if err != nil {
        fmt.Fprintf(os.Stderr, "error:%v\n", err)
    }
    //b, err := ioutil.ReadAll(resp.Body)
    cunhuo := resp.StatusCode
    defer resp.Body.Close()
    if err != nil {
        fmt.Println("Error!")
        os.Exit(1)
    }
    if cunhuo == 200 {
        fmt.Println("存在此页面:" + url + data)
    } else {
        fmt.Println("不存在此页面:" + url + data)
    }
    //fmt.Printf("%s", b)
}

}
做为一个工具我们希望它有其的灵活性,就像大多数工具一样可以给定相对应的参数
在Python中我们可以使用optparse模块来指定我们的参数
import requests
import optparse
import sys
def main():
parser =optparse.OptionParser('- u ')
parser.add_option('-u',dest='a',type='string',help="url")
options,args=parser.parse_args()
if options.a==None:
print(parser.usage)
sys.exit()
else:
url=options.a
a=url
with open("1.txt","r") as f :
b=f.read().splitlines()
for i in b:
rep=requests.get(a+str(i))
if rep.status_code == 200:
print("存在此页面:"+a+str(i))
else:
print(a+str(i)+"不存在")
if name == 'main':
main()
在Go语言中我们同样可以运用flag包去接受我们的参数
package main
import (
"bufio"
"flag"
"fmt"
"net/http"
"os"
)
func main() {
var url string
flag.StringVar(&url, "url", "", "请输入一下你的URL")
flag.Parse()
if url == "" {
fmt.Println(         ▍ ★∴    ....▍▍....█▍ ☆ ★∵ ..../     ◥█▅▅██▅▅██▅▅▅▅▅███◤     .◥███████████████◤   ~~~~◥█████████████◤~~~~ 雷石安全实验室出品 -h 查看相应步骤 版本 0.0001 )
os.Exit(1)
}
file, err := os.Open("1.txt")
if err != nil {
fmt.Printf("文件读取失败")
}
defer func() {
file.Close()
}()
n := bufio.NewScanner(file)
//fmt.Printf("%T-%d\n"m, n, n)
//fmt.Printf("%T--\n", n.Scan())
//fmt.Println(n.Scan())
for n.Scan() {
data := n.Text()
resp, err := http.Get(url + data)
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
}
//b, err := ioutil.ReadAll(resp.Body)
cunhuo := resp.StatusCode
defer resp.Body.Close()
if err != nil {
fmt.Println("Error!")
os.Exit(1)
}
if cunhuo == 200 {
fmt.Println("存在此页面:" + url + data)
} else {
fmt.Println("不存在此页面:" + url + data)
}
//fmt.Printf("%s", b)
}
}
我们有了灵活性以后,我们可以希望速度上快一点,不然我们扫完以后可能,就没有以后了(=,=)
在Python中我们可以threading模块去创建多线程
import requests
import threading
import time
import optparse
import sys
def test01(url):
try:
resp = requests.get(url, headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'})
if resp.status_code == 200:
print('[' + str(resp.status_code) + ']' + ":" + url)
else:
print(url+str(resp.status_code))
except:
pass
threadm.release()
def test02(file,url):
for i in file.readlines():
urls = url+i.strip()
threadm.acquire()
t = threading.Thread(target=test01, args=(urls,))
threads.append(t)
t.start()
for t in threads:
t.join()
if name == 'main':
start = time.time()
threads = []
threadm = threading.BoundedSemaphore(500)
parser = optparse.OptionParser('- u ')
parser.add_option('-u', dest='a', type='string', help="url")
options, args = parser.parse_args()
if options.a == None:
print(parser.usage)
sys.exit()
else:
url = options.a
f= open('1.txt',encoding='utf-8')
test02(f,url)
end = time.time()
print(end-start)
f.close()
package main
import (
"bufio"
"flag"
"fmt"
"net/http"
"os"
"sync"
"time"
)
//channel 通道是一个同步处理的过程
var wg sync.WaitGroup
//time.Time是一个结构体时间点
func testtime(start time.Time) {
fmt.Printf("耗时:%v", time.Since(start))
//func Since(t Time)Duration 表示自从t时刻以后过了多长时间,是一个时间段
}
//开启一个goroutines
func test01(file os.File, url string, urls chan string) {
n := bufio.NewScanner(file)
for n.Scan() {
var okurl = fmt.Sprintf("%s%s", url, n.Text()) // Sprintf() 是把格式化字符串输出到指定的字符串中,可以用一个变量来接受,然后在打印
urls <- okurl //向urls通道中写入完整的url
}
err := n.Err()
if err != nil {
fmt.Println("Error!")
}
close(urls)
fmt.Println("读取完毕")
}
func main() {
var url string
flag.StringVar(&url, "url", "", "请输入一下你的URL")
flag.Parse()
if url == "" {
fmt.Println(         ▍ ★∴    ....▍▍....█▍ ☆ ★∵ ..../     ◥█▅▅██▅▅██▅▅▅▅▅███◤     .◥███████████████◤   ~~~~◥█████████████◤~~~~ 雷石安全实验室出品 -h 查看相应步骤 版本 0.0001test )
os.Exit(1)
}
times := time.Now()
urls := make(chan string)
file, err := os.Open("1.txt")
if err != nil {
fmt.Println("字典打开失败: ", err)
return
}
defer testtime(times)
defer file.Close()
go test01(file, url, urls)
//开启多个goroutines
for i := 0; i < 200; i++ {
wg.Add(1)
go gourl(urls)
}
wg.Wait()
}
func gourl(urls chan string) {
for {
/

Go里面提供了一个关键字select,通过select可以监听channel上的数据流动。
select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。
select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
/
select {
case url, ok := <-urls:
if !ok {
wg.Done()
return
}
//Golang通过http.NewRequest实现模拟请求,添加请求头和请求参数:
client := &http.Client{}
request, err := http.NewRequest("HEAD", url, nil)
if err != nil {
continue
}
request.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0")
resp, err := client.Do(request)
if err != nil {
fmt.Println(err)
continue
}
if resp.StatusCode == 200 {
fmt.Printf("%s 状态码: %v\n", url, resp.StatusCode)
} else {
fmt.Printf("%s 状态码: %v\n", url, resp.StatusCode)
}
resp.Body.Close()
/
超时控制
通常我们可以通过select + time.After 来进行超时检查/
case <-time.After(time.Duration(2) * time.Second):
wg.Done()
return
}
}
}
对于GUI工具的理解:
首先要有一个模板
对比命令行下的工具,图形化的工具要有事件响应(比如邮件列出菜单)
import tkinter as tk
from tkinter.filedialog import *
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class App(Frame):
def init(self,master=None):
super(App, self).init()
super().init(master)
self.master=master
self.var = tk.StringVar()
self.zapi = "oI5pPuvuGPF5CSSRzCzk4WB8rvIYUkmM"
self.initUI()
self.textpad=None
self.Create()
self.pack()
def Create(self):
menubar=Menu(root)
menuFile=Menu(menubar)
menubar.add_cascade(label="options",menu=menuFile)
menuFile.add_command(label="shellcode",accelerator="ctrl+a",command=self.test)
menubar.add_cascade(label="test",menu=menuFile)
menuFile.add_command()
menuFile.add_command(label="open",accelerator="ctrl+b",command=self.fileopen)
menuFile.add_command(label="save",accelerator="ctrl+c",command=self.filesave)
menuFile.add_command(label="new",accelerator="ctrl+d",command=self.filenew)
root["menu"]=menubar
self.textpad=Text(root,width=200,height=10)
self.textpad.pack()
self.contextMenu=Menu(root)
//右键事件
self.contextMenu.add_command(label="一键装逼",command=self.zha)
self.contextMenu.add_command(label="bg",command=self.openAskColor)
root.bind("",self.createCon)
def zha(self):
pass
def openAskColor(self):
pass
def fileopen(self):
pass
def filesave(self):
pass
def filenew(self):
pass
def createCon(self,event):
self.contextMenu.post(event.x_root,event.y_root)
def test(self):
pass
def initUI(self):
group_top = tk.LabelFrame(self, padx=15, pady=10)
group_top.pack(padx=10, pady=5)
tk.Button(group_top, text="scanIP", width=10, command=self.scanIP).grid(row=0, column=1)
self.path_entry = tk.Entry(group_top, width=30)
self.path_entry.grid(row=0, column=0, pady=5, padx=5)
//添加按钮
tk.Button(group_top, text="开始执行", width=10, command=self.func).grid(row=1, column=1, sticky=tk.E)
tk.Button(group_top, text="停止", width=10, command=self.destroy).grid(row=1, column=0, sticky=tk.W)
console_frame = tk.Frame(group_top).grid(row=2, column=0, columnspan=2)
self.console_text = tk.Text(
console_frame, fg="green", bg="black", width=40, height=20, state=tk.DISABLED)
scrollbar = tk.Scrollbar(console_frame, command=self.console_text.yview)
self.console_text.pack(expand=1, fill=tk.BOTH)
self.console_text['yscrollcommand'] = scrollbar.set
def output_to_console(self, new_text):
self.console_text.config(state=tk.NORMAL)
self.console_text.insert(tk.END, new_text)
self.console_text.see(tk.END)
self.console_text.config(state=tk.DISABLED)
def func(self):
pass
def usage(self):
A = """
__ .__ .___ .___ .__
____________ | | || | _/| /__ ||
/ /_ | |/ / |/ __ |/ __ |__ \ | |
___ \ | |> > <| / // / // | / __ | |
/
___ >| /||_ ____ ____ |(____ /|
/ |
| / / / /
"""
B = """
*** by YanMu ***
"""
self.output_to_console(f"{A}\n");self.output_to_console(f"{B}\n")
def scanIP(self):
pass
if name == 'main':
root=Tk()
root.title("Pythonstudy by 雷石安全")
root.geometry("1200x500+200+300")
app = App(master=root)
root.resizable(height=False)
app.usage()
app.mainloop()
代码中pass地方可以写你相应的功能点
demo演示:
然后我们可以在正常的函数除填写我们相应的功能
import tkinter as tk
import shodan
from tkinter.colorchooser import *
from tkinter.filedialog import *
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class App(Frame):
def init(self,master=None):
super(App, self).init()
super().init(master)
self.master=master
self.var = tk.StringVar()
self.zapi = ""//你的api
self.initUI()
self.textpad=None
self.Create()
self.pack()
def Create(self):
menubar=Menu(root)
menuFile=Menu(menubar)
menubar.add_cascade(label="options",menu=menuFile)
menuFile.add_command(label="shellcode",accelerator="ctrl+a",command=self.test)
menubar.add_cascade(label="test",menu=menuFile)
menuFile.add_command()
menuFile.add_command(label="open",accelerator="ctrl+b",command=self.fileopen)
menuFile.add_command(label="save",accelerator="ctrl+c",command=self.filesave)
menuFile.add_command(label="new",accelerator="ctrl+d",command=self.filenew)
root["menu"]=menubar
self.textpad=Text(root,width=200,height=10)
self.textpad.pack()
self.contextMenu=Menu(root)
self.contextMenu.add_command(label="一键装逼",command=self.zha)
self.contextMenu.add_command(label="bg",command=self.openAskColor)
root.bind("",self.createCon)
def zha(self):
pass
def openAskColor(self):
s=askcolor(color="red",title="bg")
self.textpad.config(bg=s[1])
def fileopen(self):
self.textpad.delete("1.0","end")
with askopenfile(title="txt") as f:
self.textpad.insert(INSERT,f.read())
self.filename=f.name
def filesave(self):
with open(self.filename,"w") as f:
c=self.textpad.get(1.0,END)
f.write(c)
def filenew(self):
self.filename=asksaveasfile("另存为",initialfile="log.txt",filetypes=[("文本文档","
.txt")],defaultextension=".txt")
self.filesave()
def createCon(self,event):
self.contextMenu.post(event.x_root,event.y_root)
def test(self):
pass
def initUI(self):
group_top = tk.LabelFrame(self, padx=15, pady=10)
group_top.pack(padx=10, pady=5)
tk.Button(group_top, text="scanIP", width=10, command=self.scanIP).grid(row=0, column=1)
self.path_entry = tk.Entry(group_top, width=30)
self.path_entry.grid(row=0, column=0, pady=5, padx=5)
tk.Button(group_top, text="开始执行", width=10, command=self.func).grid(row=1, column=1, sticky=tk.E)
tk.Button(group_top, text="停止", width=10, command=self.destroy).grid(row=1, column=0, sticky=tk.W)
console_frame = tk.Frame(group_top).grid(row=2, column=0, columnspan=2)
self.console_text = tk.Text(
console_frame, fg="green", bg="black", width=40, height=20, state=tk.DISABLED)
scrollbar = tk.Scrollbar(console_frame, command=self.console_text.yview)
self.console_text.pack(expand=1, fill=tk.BOTH)
self.console_text['yscrollcommand'] = scrollbar.set
def output_to_console(self, new_text):
self.console_text.config(state=tk.NORMAL)
self.console_text.insert(tk.END, new_text)
self.console_text.see(tk.END)
self.console_text.config(state=tk.DISABLED)
def func(self):
se = ""//要搜索的设备
api = shodan.Shodan(self.zapi)
res = api.search(se)
# a=str(result['ip_str'])
for result in res['matches']:
url = str(result['ip_str']) + ":" + str(result['port']) + ":" + str(
result['location']['country_name']) + ":" + str(result['domains'])
# print(url)
self.output_to_console(f"{url}\n")
def usage(self):
A = """
__ .__ .___ .___ .__
____________ | | || | _/| /__ ||
/ /_ | |/ / |/ __ |/ __ |__ \ | |
___ \ | |> > <| / // / // | / __ | |
/
___ >| /||_ ____ ____ |(____ /|
/ |
| / / / /
"""
B = """
*** by YanMu ***
"""
self.output_to_console(f"{A}\n");self.output_to_console(f"{B}\n")
def scanIP(self):
pa = self.path_entry.get()
scapi = shodan.Shodan(self.zapi)
hosts = scapi.host(pa)
er = str(hosts['ip_str']) + ":" + str(hosts.get('org', 'n/a')) + ":" + str(hosts.get('os', 'n/a'))
self.output_to_console(f"{er}\n")
for host in hosts['data']:
sas = str(host['port']) + ":" + str(host['data'])
self.output_to_console(f"{sas}\n")
if name == 'main':
root=Tk()
root.title("Pythonstudy by 雷石安全")
root.geometry("1200x500+200+300")
app = App(master=root)
root.resizable(height=False)
app.usage()
app.mainloop()
这里我们填写shodan的搜索为例,当然当时练习的时候尝试写一个记事本的功能来着
GUI个人思路:
有一个样式框架,往里面填东西就行。
你可以把别人命令行式的代码,剪吧剪吧放到自己的工具里面(缺陷:这个demo不能及时反映响应信息)
最后介绍一下,B/S架构思考:
这里我用的tornado框架
还是先有一个模板
import tornado.web
import os
import shodan
import tornado.ioloop
import tornado.httpserver
from tornado.options import define,options,parse_command_line
define("port",default=8888,help="运行端口",type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def write_error(self, status_code, **kwargs):
self.write("your caused a %d error."%status_code)
class CoupletHandler(tornado.web.RequestHandler):
def post(self):
first=self.get_argument("first")
second=self.get_argument("second")
self.render("couplet.html",first=sumurls,second=second)
if name == 'main':
parse_command_line()
print("""

        logo:leishi
        by caibi-yanmu

""")
print("http://localhost:{}/".format(options.port))
base_dir=os.path.dirname(__file__)
app=tornado.web.Application(
    handlers=[
        (r"/",IndexHandler),
        (r"/couplet",CoupletHandler)
    ],
    template_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'templates'),
    static_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'static'),
)
http_server=tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()

然后我们向这个demo里面加我们的功能点
这里主要方便测试(外表不重要,嘤嘤嘤)
import tornado.web
import os
import shodan
import tornado.ioloop
import tornado.httpserver
from tornado.options import define,options,parse_command_line
define("port",default=8888,help="运行端口",type=int)
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def write_error(self, status_code, **kwargs):
self.write("your caused a %d error."%status_code)
class CoupletHandler(tornado.web.RequestHandler):
def post(self):
first=self.get_argument("first")
second=self.get_argument("second")
api=shodan.Shodan(first)
sumurls=""
try:
results=api.search(second)
for i in results['matches']:
url=i['ip_str']+":"+str(i['port'])
sumurls+=url+"\n"
except shodan.APIError as e:
print(e)
self.render("couplet.html",first=sumurls,second=second)
if name == 'main':
parse_command_line()
print("""

        logo:leishi
        by caibi-yanmu

""")
print("http://localhost:{}/".format(options.port))
base_dir=os.path.dirname(__file__)
app=tornado.web.Application(
    handlers=[
        (r"/",IndexHandler),
        (r"/couplet",CoupletHandler)
    ],
    template_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'templates'),
    static_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'static'),
)
http_server=tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()

这里师傅们可以根据自己的前端代码去填充对应结果
总结:
我们平常写的命令行下的工具无论是在GUI形式下还是B/S形式下,最后核心的功能点不变,所以说,要是我们平常在测试的过程中,完全可以只写在命令行模式下的小工具。

标签:url,os,self,command,tk,编写,随笔,tools,def
来源: https://www.cnblogs.com/YanMublogs/p/14618334.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有