set(PROJECT_NAME ext_server_kiwi)

project(${PROJECT_NAME} C)

include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeListsFuncs.txt)

add_definitions(
    -D_WINDLL
    -D_USRDLL
    -DUNICODE
    -D_UNICODE
    -D_POWERKATZ
)

if(MSVC)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
else()
    add_definitions(
        '-D_WIN32_WINNT=0x601'
        '-D__deref=SAL__deref'
        '-D__deref_opt_bcount=SAL__deref_opt_bcount'
        '-D__deref_opt_out_bcount=SAL__deref_opt_out_bcount'
        '-D__deref_opt_out_opt=SAL__deref_opt_out_opt'
        '-D__deref_out=SAL__deref_out'
        '-D__deref_out_bcount=SAL__deref_out_bcount'
        '-D__deref_out_bcount_opt=SAL__deref_out_bcount_opt'
        '-D__deref_out_bcount_full=SAL__deref_out_bcount_full'
        '-D__deref_out_ecount_full=SAL__deref_out_ecount_full'
        '-D__field_bcount=DISCARD'
        '-D__field_ecount=DISCARD'
        '-D__field_xcount=DISCARD'
        '-D__in_bcount_opt=SAL__in_bcount_opt'
        '-D__in_ecount_opt=SAL__in_ecount_opt'
        '-D__in_ecount_opt=SAL__in_ecount_opt'
        '-D__format_string=SAL__format_string'
        '-D__in_z='
        '-D__inout_bcount_opt=SAL__inout_bcount_opt'
        '-D__inout_bcount_part_opt=SAL__inout_bcount_part_opt'
        '-D__out_bcount_full_opt=SAL__out_bcount_full_opt'
        '-D__out_bcount_opt=SAL__out_bcount_opt'
        '-D__out_bcount_part_opt=SAL__out_bcount_part_opt'
        '-D__out_ecount_opt=SAL__out_ecount_opt'
        '-D__out_xcount_opt=SAL__out_bcount_opt'
        '-D__range=DISCARD2'
        '-D__reserved=SAL__reserved'
        '-D__success=DISCARD'
        '-D__FUNCTION__=""'
        '-D__struct_bcount=DISCARD'
    )
endif()

include_directories(../../source/common)
include_directories(../../source/ReflectiveDLLInjection/common)
include_directories(../../source/extensions/kiwi/mimikatz/inc)

set(SRC_DIR ../../source/extensions/kiwi)

# Unfortunately we have to be a little judicious with what we include
file(GLOB SRC_FILES
    ${SRC_DIR}/*.c
    ${SRC_DIR}/mimikatz/modules/*.c
    ${SRC_DIR}/mimikatz/modules/rpc/*.c
    ${SRC_DIR}/mimikatz/mimikatz/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/crypto/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/dpapi/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/dpapi/packages/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/kerberos/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/lsadump/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/lsadump/packages/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/sekurlsa/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/sekurlsa/crypto/*.c
    ${SRC_DIR}/mimikatz/mimikatz/modules/sekurlsa/packages/*.c
    ${MOD_DEF_DIR}/extension.def
)

# Ditch some old stuff that shouldn't even be here in the mimikatz repo!
list(REMOVE_ITEM SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_DIR}/mimikatz/mimikatz/modules/kuhl_m_dpapi.c)

add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}.${TARGET_ARCH})
if(MSVC)
    set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DEF:\"${MOD_DEF_DIR}/extension.def\"")
    set_source_files_properties(${MOD_DEF_DIR}/extension.def PROPERTIES HEADER_FILE_ONLY TRUE)
endif()

if(IS_X86)
    set(KIWI_LIB_DIR ${WORKSPACE_ROOT_DIR}/../source/extensions/kiwi/mimikatz/lib/Win32)
else()
    set(KIWI_LIB_DIR ${WORKSPACE_ROOT_DIR}/../source/extensions/kiwi/mimikatz/lib/x64)
endif()

set(LINK_LIBS
    advapi32
    psapi
    crypt32
    shlwapi
    secur32
    wtsapi32
    winscard
    wldap32
    netapi32
    rpcrt4
    setupapi
    userenv
    cabinet
    dnsapi
    version
)

if(MSVC)
    set(LINK_LIBS
        ${LINK_LIBS}
        msxml2
    )
endif()

# Add all the custom libs that come with the mimikatz source
set(LINK_LIBS
    ${LINK_LIBS}
    ${KIWI_LIB_DIR}/cryptdll.lib
    ${KIWI_LIB_DIR}/fltlib.lib
    ${KIWI_LIB_DIR}/hid.lib
    ${KIWI_LIB_DIR}/msasn1.min.lib
    ${KIWI_LIB_DIR}/ncrypt.lib
    ${KIWI_LIB_DIR}/netapi32.min.lib
    ${KIWI_LIB_DIR}/ntdll.min.lib
    ${KIWI_LIB_DIR}/samlib.lib
    ${KIWI_LIB_DIR}/winsta.lib
    ${KIWI_LIB_DIR}/advapi32.hash.lib
)

target_link_libraries(${PROJECT_NAME} ${LINK_LIBS})
if(MSVC)
    target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070")
endif()

# Post processing (required for all Meterpreter DLLs)
editbin(${PROJECT_NAME} ${BIN_SUBSYSTEM})
copyoutput(${PROJECT_NAME} ${BIN_OUTPUT_DIR})
