uctf-雜項題目分析
BP 斷點
分數:100 描述: 提示 1:key 不是大家喜歡的波波老師!
提示 2:bmp+png
提示 3:CRC Link: http://pan.baidu.com/s/1o6x4FEE
Bmp 只是誘餌,給大家看看波波老師。關鍵在於 png 圖片,根據 png 格式圖片,以及提示,很明顯可以想到利用 crc 去爆破寬度和高度。可以用 c 或者 py,py 在這題爆破三個位元組還是可以的,如果位元組太多還是用 c 吧。 之所以名字叫做 BP 斷點,是因為是 bmp+png 的圖片。
參考 c 程式碼:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
//crc32.h
#ifndef _CRC32_H
#define _CRC32_H
UINT crc32( UCHAR *buf, int len);
#endif
static UINT CRC32[256];
static char init = 0;
//初始化表
static void init_table()
{
int i,j;
UINT crc;
for(i = 0;i < 256;i++)
{
crc = i;
for(j = 0;j < 8;j++)
{
if(crc & 1)
{
crc = (crc >> 1) ^ 0xEDB88320;
}
else
{
crc = crc >> 1;
}
}
CRC32[i] = crc;
}
}
//crc32實現函式
UINT crc32( UCHAR *buf, int len)
{
UINT ret = 0xFFFFFFFF;
int i;
if( !init )
{
init_table();
init = 1;
}
for(i = 0; i < len;i++)
{
ret = CRC32[((ret & 0xFF) ^ buf[i])] ^ (ret >> 8);
}
ret = ~ret;
return ret;
}
int main()
{
char sss[17]="\x49\x48\x44\x52\x00\x00";
int a1,a2,a3,a4,a5,a6,a7,a8;
int _crc32 = 0;
for (a3=0x00;a3<=0xff;a3++)
for (a4=0x00;a4<=0xff;a4++)
for (a7=0x00;a7<=0xff;a7++)
for (a8=0x00;a8<=0xff;a8++)
{
sss[6]=(char)a3;
sss[7]=(char)a4;
sss[8]='\x00';
sss[9]='\x00';
sss[10]=(char)a7;
sss[11]=(char)a8;
sss[12]='\x08';sss[13]='\x06';sss[14]='\x00';sss[15]='\x00';sss[16]='\x00';
sss[17]='\x00';
_crc32 = crc32((UCHAR *)sss, 17);
if(_crc32 == 0x80BF36CC)
{
printf("%s,%x,%x,%x,%x\n", sss,a3,a4,a7,a8);
}
}
return 0;
}
最後結果:
參考 python 程式碼:
# -*- coding:utf-8 -*-import binascii
#注意返回的是小寫 形如:"0x1c4d1d3cL", 並且為字串。
def CalcCrc32(str):
return hex(binascii.crc32(str) & 0xFFFFFFFF)
if __name__=="__main__":
str1 = '\x49\x48\x44\x52\x00\x00\x01'
str2 = '\x00\x00'
str3 = '\x08\x06\x00\x00\x00'
int1 = 0
int2 = 0
int3 = 0
for int1 in range(0,256):
for int2 in range(0, 256):
for int3 in range(0, 256):
m = str1 + chr(int1) + str2 + chr(int2) + chr(int3) + str3
if (CalcCrc32(m) == "0x80bf36ccL"):
print "Yeah, U Found it!"
print hex(int1)
print hex(int2)
print hex(int3)
exit()
跑幾分鐘後,結果就出來了。
聽聽音樂
先下載壓縮包 http://pan.baidu.com/s/1bncmvuR 解壓後發現兩個檔案Music.exe
,Readme.doc
. 要求利用 xp sp3 對目標程式進行溢位 既然是比賽,那麼肯定就是要有溢位點的啦 直接開啟 exe,聽到了甩蔥歌 於是不準備關掉他了, 新開一個例程,OD 載入
發現是 VC6 連結的 於是就果斷去找 main 函式了 不過 exe 程式居然自殺了,不能聽甩蔥歌,差評 果斷定位到了 main
寫入內容為 exe 的啟動引數 於是猜想啟動引數這個地方應該就是所謂的溢位點 於是寫了一個簡單程式,介面如下
最後發現 273 程式就會崩潰 於是使用 273 建立程式 OD 附加並設定 F2 斷點於 ReadFile 於多次返回後定位到
觀察堆疊後發現 此時已覆蓋[esp]一個位元組 Ret 後肯定會跳轉到記憶體中某一被修改的位置執行程式碼 於是構建 shellcode 記憶體收縮
FF E4 (jmp esp)
最終定位到 0x77D29353
,開啟 010 editor
,構建 exp.
接下來構造功能程式碼 之後我發現程式段裡竟然有可恥的 call eax 找了個地址比較吉利的構造了下 用阿爾法轉換了下 shellcode 最終 exp 如下
最簡單的加解密
分數:300 描述: 提示 1:DES
提示 2:凱撒
得到兩串二進位制後,轉換為 16 進位制分別為:
0x4d3259784e7a49304f444a6f4e57746f4e44597a61575a6d4d3267785a6a5a6e5a6d59344d4763344f544d354f4441784f5774724e4449796144566d4f446730L
0x5379636c30763372L
轉換為字串分別為:
M2YxNzI0ODJoNWtoNDYzaWZmM2gxZjZnZmY4MGc4OTM5ODAxOWtrNDIyaDVmODg0
Sycl0v3r
可以認為第一個字串為 DES 的密文,第二個字串為 DES 的金鑰。解密發現不對。但是根 據大小寫和數字可以猜測為 base64,解密後的字串:
3f172482h5kh463iff3h1f6gff80g89398019kk422h5f884
再用 DES 的金鑰解密,發現還是不對。根據提示“凱撒”去解碼試試。
http://crypo.in.ua/tools/eng_caesar.php
解幾次後發現 3a172482c5fc463daa3c1a6baa80b89398019ff422c5a884
這串是可以用DES 解密的。
表白牆
在輸出”tell me:”之後程式會讀入使用者輸入,但這裡使用了危險的 scanf(“%s”)而沒有任何額外 的檢查,直接輸入超長字串就可以造成 buffer overflow。
成功利用彈 MessageBox 的截圖如下
P.S:其實程式裡還有一個格式化字串漏洞,不過那個利用起來沒這個方便,所以就直接 用這個了。
找女朋友
載入到 od 中執行程式,程式發現了我們啟動了 od,並列印出了 SOD 的驅動名
程式 main 函式在0x401000
處,在這裡用了 EnumDeviceDrivers
和 GetDeviceDriverFileNameA
函式來列舉系統中已經載入的驅動,並判斷 dbghelp.dll 路徑與系統路徑是否相同,如果不同 就認為系統中執行了 od 驅動物件的 DriverSection 儲存了一個指向_LDR_DATA_TABLE_ENTRY 指標,這個結構中有著一 個所有驅動的連結串列,透過遍歷這個連結串列就可以知道載入了哪些驅動,如果想要程式找不到一 個驅動,我們只需要從這個連結串列中把相應的驅動摘下來 以下是具體程式碼:
#include <ntddk.h>
#define INITCODE code_seg("INIT")
#define PAGECODE code_seg("PAGE")
#define PROCESS_ID_OFFSET 0x84
#define IMAGE_NAME_OFFSET 0x174
#define PROCESS_LINK_OFFSET 0x88
#define PROCESS_EXITTIME 0x78
typedef struct _SYSTEM_SERVICE_TABLE
{
PVOID *ServiceTableBase;
PULONG *ServiceCounterTableBase;
ULONG NumberOfServices;
ULONG ParamTableBase;
}SSDT, *PSSDT;
__declspec(dllimport) SSDT KeServiceDescriptorTable;
//_LDR_DATA_TABLE_ENTRY 宣告
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
ULONG TimeDateStamp;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
/////////////////////////////////////////////////////////////
void DriverUnload(IN PDRIVER_OBJECT pDriverObject);
void ShowProcess();
struct _LIST_ENTRY *tmp;
/////////////////////////////////////////////////////////////
#pragma INITCODE
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath)
{
PLDR_DATA_TABLE_ENTRY pTableEntry = NULL;
PLIST_ENTRY pCur = NULL, pHead = NULL;
UNICODE_STRING str_Name;
ULONG EProcess,FirstEProcess;
LIST_ENTRY* ActiveProcessLinks;
ULONG pid,dwCount=0;
PUCHAR pImage;
//PPROCESS_INFO ProcessInfo={0};
pDriverObject->DriverUnload = DriverUnload;
RtlInitUnicodeString(&str_Name, L"fengyue0.sys");
//從驅動物件中的 DriverSection 獲得_LDR_DATA_TABLE_ENTRY 指標
pTableEntry = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
//使頭指標和當前指標指向模組連結串列中的一個模組
pCur = pHead = pTableEntry->InLoadOrderLinks.Blink;
do
{
//獲得模組指標
pTableEntry = (PLDR_DATA_TABLE_ENTRY)pCur;
if (pTableEntry->BaseDllName.Buffer)
{
if (RtlCompareUnicodeString(&str_Name, &(pTableEntry->BaseDllName), FALSE) ==
0)
{
//從連結串列中刪除模組
pTableEntry->InLoadOrderLinks.Blink->Flink =
pTableEntry->InLoadOrderLinks.Flink;
pTableEntry->InLoadOrderLinks.Flink->Blink =
pTableEntry->InLoadOrderLinks.Blink;
break;
}
}
pCur = pCur->Flink;
}while (pCur != pHead);
/////////////////////////////////////////////////////////////
//顯示程式
ShowProcess();
return STATUS_SUCCESS;
}
#pragma PAGECODE
void DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
}
void ShowProcess()
{
ULONG OriFunAddr;
UNICODE_STRING str_FuncName;
PULONG ssdt_base;
RtlInitUnicodeString(&str_FuncName,L"NtQuerySystemInformation");
//獲取 ssdt 基址
ssdt_base = (PULONG) KeServiceDescriptorTable.ServiceTableBase;
//獲取 NtQuerySystemInformation 原地址
OriFunAddr =(ULONG) MmGetSystemRoutineAddress(&str_FuncName);
//判斷當前 ssdt 中地址是否被替換
if (ssdt_base[0xAD] != OriFunAddr)
{
DbgPrint("NtQuerySystemInformation has been hooked!fix it...");
ssdt_base[0xAD] = OriFunAddr;
DbgPrint("success!");
}
}
題目中的第二個目標就是使 od 程式在 windows 自帶的工作管理員中顯示出來, fengyue0.sys 驅動會在 ssdt 中把 NtQuerySystemInformation
函式 hook 掉,所以,當 windows 的任務管理 器透過這個函式列舉程式的時候就會把 od 程式隱藏了
知道了隱藏的原理之後,我們的目標就轉換為了,把 NtQuerySystemInformation
的 ssdt hook 給恢復了。 在 KeServiceDescriptorTable
中可以獲得 ssdt 的基地址,再透過 NtQuerySystemInformation
在 ssdt 中的索引號就可以得到在 ssdt 中存放的它的地址,但是 ssdt 中的地址不一定是函式真 正的地址,有可能是被 hook 了的地址,所以可以再 MmGetSystemRoutineAddress 獲得函式 真正的地址,然後與 ssdt 中的對比,如果相同則說明函式沒有被 hook,反之函式被 hook, 我們的目的是恢復它的真正地址,現在既然已經有了真正的地址,就可以直接把 ssdt 中的 假地址給換掉,就恢復了 NtQuerySystemInformation
的 ssdt hook。具體程式碼在上述程式碼的 ShowProcess()函式中。
用 od 加 載 目 標 程 序 後 , 把 我 們 的 驅 動 用 DriverMonitor 加 載 並 運
之後在 od 中執行目標程式
程式顯示沒有發現 od,說明我們隱藏驅動成功了,再到 windows 工作管理員中檢視一下, ollydbg.exe 程式也出現了
相關文章
- [雜項] 刷題記錄2024-07-30
- 雜項2024-05-01
- *CTF babyarm核心題目分析2022-04-19
- Codeforces 250 題目分析2024-11-18
- React 常用面試題目與分析2017-01-17React面試題
- Git雜項2024-08-03Git
- Codeforces 1145 題目分析2024-11-20
- 一些CTF雜項MISC解題指令碼2020-12-13指令碼
- 雜項 tips2020-08-07
- jQuery 雜項方法2022-08-09jQuery
- Spark Special_楊寧遠 雜題分析.md2024-07-07Spark
- bugku一道逆向題目分析2022-04-27
- SCTF 2014 pwn題目分析2016-05-11
- 數對數目;及LIS問題分析2013-11-01
- 【odoo】【知識雜談】單一例項多庫模式下定時任務的問題分析2021-09-06Odoo模式
- 反除錯:雜項2022-01-18除錯
- css雜項補充2018-09-27CSS
- LINUX命令雜項2011-07-01Linux
- 【筆記】Tricks - 雜項2024-06-26筆記
- 題目:刪除排序陣列中的重複項2020-11-19排序陣列
- 複雜度分析2024-03-20複雜度
- PHP 設計模式(雜項)2017-05-27PHP設計模式
- 雜項知識統計2017-11-21
- 圖論雜項小技巧2024-03-30圖論
- 數學——數論/雜項2024-04-13
- 雜題部分2024-11-09
- 資料分析雜談2020-09-19
- 雜項——矩陣加速(進階)2024-09-17矩陣
- 雜題選寫2024-10-10
- 10月雜題2024-10-25
- 5月雜題2024-05-08
- 雜題記錄2024-07-18
- 9月雜題2024-09-11
- ceph-pg雜湊分析2020-01-19
- Shell排序複雜度分析2024-03-09排序複雜度
- 面試題目2011-09-08面試題
- 【雜項】Substance Painter 學習筆記2020-09-30AI筆記
- 05_雜項裝置驅動2024-04-22