---
title: 常用命令
date: 2021-11-26 16:18:00
author: shedding_ash
#img: /source/images/xxx.jpg
#top: true
#cover: true
#coverImg: /images/1.jpg
#password: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
#toc: false
#mathjax: false
summary: 这是你自定义的文章摘要内容,如果这个属性有值,文章卡片摘要就显示这段文字,否则程序会自动截取文章的部分内容作为摘要
categories: pwn
tags:
- pwn
- 命令
---

GCC

查看文件头信息readelf -h 文件名

查看十六进制数据

  1. 完整显示:xxd 文件名 | od -A x -t x1z 文件名
  2. 部分显示:od --skip bytes=偏移地址 --read-bytes=字节数 -A x -t x1z 文件名

检索程序导入的函数objdump -R 文件名

查看程序所有函数及反汇编objdump -d 文件名

反汇编整个文件ndisasm -u 文件名

查找ROPROPgadget --binary 文件名

过滤ROPROPgadget --binary 文件名 --only '指令1|指令2'

运行程序./文件名

通过python构造payloadpython -c 'print "payload"' | ./文件名

将文件内容作为输入cat payload文件 -| ./文件名

生成字符串队列cyclic 字符数

计算字符串偏移cyclic -l 四个字母

连接远程服务器nc ip地址 port

下载远程目录中的程序scp -P 端口号 -p IP地址:路径/* ./

自动生成ROP链(若存在),只适用于静态链接程序ROPgadget --binary 文件名 --ropchain

gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:

  • 1、预处理,生成 .i 的文件[预处理器cpp]
  • 2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]
  • 3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]
  • 4、连接目标代码, 生成可执行程序 [链接器ld]

-c

只激活预处理,编译,和汇编,也就是他只把程序做成obj文件

例子用法:

gcc -c hello.c 

他将生成 .o 的 obj 文件

-S

只激活预处理和编译,就是指把文件编译成为汇编代码。

例子用法:

gcc -S hello.c 

他将生成 .s 的汇编代码,你可以用文本编辑器察看。

-E

只激活预处理,这个不生成文件, 你需要把它重定向到一个输出文件里面。

例子用法:

gcc -E hello.c > pianoapan.txt 
gcc -E hello.c | more

慢慢看吧, 一个 hello word 也要与处理成800行的代码。

-o

制定目标名称, 默认的时候, gcc 编译出来的文件是 a.out, 很难听, 如果你和我有同感,改掉它, 哈哈。

例子用法:

gcc -o hello.exe hello.c (哦,windows用习惯了) 
  gcc -o hello.asm -S hello.c

-pipe

使用管道代替编译中临时文件, 在使用非 gnu 汇编工具的时候, 可能有些问题。

gcc -pipe -o hello.exe hello.c 

-C

在预处理的时候, 不删除注释信息, 一般和-E使用, 有时候分析程序,用这个很方便的。

-M

生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用 gcc -M hello.c 来测试一下,很简单。

-g

只是编译器,在编译的时候,产生调试信息。

-static

此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么动态连接库,就可以运行。

-share

此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。

-traditional

试图让编译器支持传统的C语言特性。


一、-g
-g可执行程序包含调试信息
-g为了调试用的
加个-g 是为了gdb 用,不然gdb用不到

二、-o
-o指定输出文件名
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
一般语法:
gcc filename.c -o filename
上面的意思是如果你不打 -o filename(直接gcc filename.c )
那么默认就是输出a.out.这个-o就是用来控制输出文件的。 ------用./a.out执行文件

三、-c
-c 只编译不链接
产生.o文件,就是obj文件,不产生执行文件

四、-D
其意义是添加宏定义,这个很有用。

当你想要通过宏控制你的程序,不必傻乎乎的在程序里定义,然后需要哪个版本,去修改宏。

只需要在执行gcc的时候,指定-D,后面跟宏的名称即可。

示例:

gcc test.c -o test -D OPEN_PRINTF_DEBUG

或者gcc test.c -o test -DOPEN_PRINTF_DEBUG

两者都是可以的。

五、-w
-w的意思是关闭编译时的警告,也就是编译后不显示任何warning,因为有时在编译之后编译器会显示一些例如数据转换之类的警告,这些警告是我们平时可以忽略的。

六、-W和-Wall
-W选项类似-Wall,会显示警告,但是只显示编译器认为会出现错误的警告。

-Wall选项意思是编译后显示所有警告

七、-O3
-O是大写字母O,不是数字0哦。

意思是开启编译优化,等级为三。

八、-shared
如果想创建一个动态链接库,可以使用 gcc的-shared选项。输入文件可以是源文件、汇编文件或者目标文件。

九、-fPIC
-fPIC 选项作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code)
这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

例1:image-20211114111106467
例2:image-20211114111115499

-l(小写的l)参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?
就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。

好了现在我们知道怎么得到库名了,比如我们自已要用到一个第三方提供的库名字叫libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)。放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了。
但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它放在/usr/X11R6/lib目录下,我们编译时就要用-L /usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest
————————————————
版权声明:本文为CSDN博主「幽冥之花」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_30011277/article/details/103711155

GDB

选择文件

gdb 文件名
gdb ; file 文件名
附加进程:attach 进程ID

运行:run

将文件数据作为运行参数:run < file

运行至程序入口:start

单步步入:si

单步步过:ni

在指定函数设置断点:b 函数名

在指定地址设置断点:b *地址

继续运行程序:continue | c

查看所有寄存器的值:reg

查看指定寄存器的值:p $寄存器代号

查看内存布局:i proc mappings

查看内存数据:

以反汇编形式查看数据:x/[字节数]i 地址
以32位十六进制形式查看数据:x/[字节数]wx 地址
以64位十六进制形式查看数据:x/[字节数]gx 地址
查看函数调用情况:backtrace | bt

查看栈数据:stack

查看所有函数定义:i functions

查看指定函数反汇编代码:disassemble 函数名

查看当前函数反汇编代码:disassemble $pc

查看libc动态地址:libc

查找字符串所在地址:search ‘字符串’
————————————————
版权声明:本文为CSDN博主「lzyddf」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41988448/article/details/103124339

GDB常用的调试命令

一大波命令来袭,hold,或者jump
(gdb)help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h

(gdb)run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r

(gdb)start:单步执行,运行程序,停在第一执行语句

(gdb)list:查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数),简写l

(gdb)set:设置变量的值

(gdb)next:单步调试(逐过程,函数直接执行),简写n

(gdb)step:单步调试(逐语句:跳入自定义函数内部执行),简写s

(gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt

(gdb)frame:切换函数的栈帧,简写f

(gdb)info:查看函数内部局部变量的数值,简写i

(gdb)finish:结束当前函数,返回到函数调用点

(gdb)continue:继续运行,简写c

(gdb)print:打印值及地址,简写p

(gdb)quit:退出gdb,简写q

(gdb)break+num:在第num行设置断点,简写b

(gdb)info breakpoints:查看当前设置的所有断点

(gdb)delete breakpoints num:删除第num个断点,简写d

(gdb)display:追踪查看具体变量值

(gdb)undisplay:取消追踪观察变量

(gdb)watch:被设置观察点的变量发生修改时,打印显示

(gdb)i watch:显示观察点

(gdb)enable breakpoints:启用断点

(gdb)disable breakpoints:禁用断点

(gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元

(gdb)run argv[1] argv[2]:调试时命令行传参

以上就是GDB的命令其中的部分,下面列详细写一些基础常用的命令:

**list **

list 可写为l,可以列出所调试程序的代码

image-20211114113335310

1.list+linenumber
可以列出linenumber附近的代码
2.list function
可以列出函数上下文的源程序

run&quit

在GDB中如何将程序运行起来,此时只要输入run命令,就可以将命令跑起来
而quit则是退出GDB调试

break

image-20211114113349815

gdb调试时使用break命令来设置断点,有如下几种下断点地方法

break < function >

在进入指定的函数function时既停止运行,C++中可以使用class::function或function(type, type)格式来指定函数名称

break < lineNumber>
在指定的代码行打断点

break +offset/break -offset
在当前行的前面或后面的offset行打断点,offset为自然数

break filename:lineNumber
在名称为filename的文件中的第lineNumber行打断点

break filename:function
在名称为filename的文件中的function函数入口处打断点

break *address
在程序运行的内存地址处打断点

break
在下一条命令处停止运行

break … if < condition>
在处理某些循环体中可使用此方法进行调试,其中…可以是上述的break lineNumber、break +offset/break -offset中的参数,其中condition表示条件,在条件成立时程序即停止运行,如设置break if i=100表示当i为100时程序停止运行。

查看断点时,也可以使用info命令如info breakpoints [n]、info break [n]其中n 表示断点号来查看断点信息。

可以通过delete命令删除所有的断点

next

使用next命令单步执行程序代码,next的单步不会进入函数的内部,与next对应的step命令则在单步执行一个函数时进入函数内部,类似于VC++中的step into.
其用法如下

next <count>
单步跟踪,如果有函数调用不会进入函数,如果后面不加count表示一条一条的执行,加count表示执行后面的count条指令

continue
当程序遇到断点停下来之后,可以执行continue继续执行到下一个断点或到程序结束

print

print可以缩写为p,可以通过print命令查看参数或程序运行数据

值得注意的是print输出可以指定输出格式:

x按16进制格式显示变量

d按十进制显示变量

u按十六进制格式显示无符号整形

o按八进制格式显示变量

t按二进制格式显示变量

c按字符格式显示变量

f按浮点数格式显示变量

GDB查看,执行汇编语言

查看汇编 disassemble

image-20211114113739429

那么我如果要是在红箭头出进行下断如何下?

image-20211114113810926

还有这种随源码一起排列的,是不是很直观:

image-20211114113824593

再补充几条命令
backtrace(直译回溯)(bt)

当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用这条命令来查看当前的栈中的所有信息。人为的将程序下断停住,直接上图:

image-20211114113848262

bt n
显示栈顶的几个层的信息

bt -n
显示栈底下的几层信息

but,如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。(就有了下面这条命令)

frame(帧)(f)

f

n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

up
表示向栈的上面移动n层,可以不打n,表示向上移动一层。

down
表示向栈的下面移动n层,可以不打n,表示向下移动一层。

info f
会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内
地址

image-20211114114008724

(以下讲解没有截图,为避免审美疲劳,请适度观看)

print(p)
 可以输出东西可多,全局变量,静态全局变量,局部变量,如果你的局部变量和全局变量发生冲突(也就是重名),一般情况下是局部变量会隐藏全局变量。
查看全局变量,利用::,例如在1.c中看x

gdb)p “1.c”::x

数组(动

p *array@len
array:数组的首地址,len:数据的长度
(gdb) p *array@len
$1 = {1, 2, 3, 4, 5}
(静)
直接p数组名

所有寄存器的值

info registers

查看指定的寄存器的值

p $eip

结构体
如果你想很漂亮的输出结构体请设置

set print pretty on
打开print pretty这个东西,没错,输出很漂亮滴,

总而言之,p很强大,只要你想输出。
————————————————
版权声明:本文为CSDN博主「whoah」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/awm_kar98/article/details/82840811

pwntools

导入pwntools:from pwn import *

输出调试信息:context.log_level = ‘debug’

设置cpu架构:context.arch = ‘i386’/‘amd64’

远程连接:sh = remote(‘IP’,PORT)

本地运行:sh = process(‘./elf’)

发送数据:sh.send(data)

发送数据,并在末尾加上换行符(\n):sh.sendline(data)

在指定字符出现后输入指定字符串:sh.sendafter(‘等待的字符串’, ‘输入的字符串’)

在指定字符出现后输入指定字符串与回车:sh.sendlineafter(‘等待的字符串’, ‘输入的字符串’)

接收数据,numb指定字节数,timeout指定超时时间:sh.recv(numb=4096, timeout=default)

接收一行数据,keepends表示是否保留行尾的换行符(\n):sh.recvline(keepends=True)

一直接收到字符串delims出现,drop表示是否保留参数1:sh.recvuntil(delims, drop=False)

一直接收数据直到EOF:sh.recvall()

进入shell模式:sh.interactive()

附加gdb调试:gdb.attach(sh)

加载elf文件:elf = ELF(‘[文件名]’)

查看指定函数的PLT地址:function_plt = elf.plt[‘函数名’]

定位字符串静态偏移:elf.search(‘字符串’).next()

将整数转换成32位的小端字节序:p32(整数)

将4个字节转换成最多4字节的整数:u32(字符串.ljust(4, ‘\x00’))

将整数转换成64位的小端字节序:p64(整数)

将8个字节转换成最多8字节的整数:u64(字符串.ljust(8, ‘\x00’))

生成指定字符数量的字符串:str = cyclic(字符数)

查找指定字符串偏移:index = cyclic_find(‘四个字母’)

生成一段shellcode汇编代码:shellcode = shellcraft.sh()

编译shellcode汇编代码为字节码:shellcode = asm(shellcraft.sh())