mimikatz/modules/kull_m_acr.c

130 lines
3.8 KiB
C

/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_acr.h"
BOOL kull_m_acr_init(SCARDCONTEXT hContext, LPCWSTR szReaderName, BOOL withoutCard, LPVOID suppdata, BOOL descr, PKULL_M_ACR_COMM comm)
{
BOOL status = FALSE;
DWORD dwActiveProtocol;
LONG scStatus;
comm->hCard = 0;
comm->withoutCard = withoutCard;
comm->suppdata = suppdata;
comm->descr = descr;
scStatus = SCardConnect(hContext, szReaderName, withoutCard ? SCARD_SHARE_DIRECT : SCARD_SHARE_SHARED, withoutCard ? SCARD_PROTOCOL_UNDEFINED : SCARD_PROTOCOL_Tx, &comm->hCard, &dwActiveProtocol);
if(!(status = (scStatus == SCARD_S_SUCCESS)))
PRINT_ERROR(L"SCardConnect: 0x%08x\n", scStatus);
return status;
}
void kull_m_acr_finish(PKULL_M_ACR_COMM comm)
{
LONG scStatus;
if(comm->hCard)
{
scStatus = SCardDisconnect(comm->hCard, SCARD_LEAVE_CARD);
if(scStatus == SCARD_S_SUCCESS)
comm->hCard = 0;
else PRINT_ERROR(L"SCardDisconnect: 0x%08x\n", scStatus);
}
}
BOOL kull_m_arc_sendrecv(PKULL_M_ACR_COMM comm, const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult)
{
BOOL status = FALSE;
LONG scStatus;
DWORD ret = *cbResult;
if(comm->hCard)
{
if(cbData <= ACR_MAX_LEN)
{
if(comm->descr)
{
kprintf(L"ACR > ");
kull_m_string_wprintf_hex(pbData, cbData, 1);
kprintf(L"\n");
}
scStatus = comm->withoutCard ?
SCardControl(comm->hCard, IOCTL_CCID_ESCAPE, pbData, cbData, pbResult, *cbResult, &ret) :
SCardTransmit(comm->hCard, NULL, pbData, cbData, NULL, pbResult, &ret);
if(scStatus == SCARD_S_SUCCESS)
{
if(comm->descr)
{
kprintf(L"ACR < ");
kull_m_string_wprintf_hex(pbResult, ret, 1);
kprintf(L"\n");
}
if(status = (ret <= *cbResult))
*cbResult = (UINT16) ret;
}
else PRINT_ERROR(L"%s: 0x%08x\n", comm->withoutCard ? L"SCardControl" : L"SCardTransmit", scStatus);
}
else PRINT_ERROR(L"cbData = %hu / cbResult = %hu (max is %hu)\n", cbData, cbResult, ACR_MAX_LEN);
}
else PRINT_ERROR(L"No handle to Card\n");
return status;
}
BOOL kull_m_acr_sendrecv_ins(PKULL_M_ACR_COMM comm, BYTE cla, BYTE ins, BYTE p1, BYTE p2, const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult, BOOL noLe)
{
BOOL status = FALSE;
BYTE buffer[ACR_MAX_LEN], idx = 4;
//BYTE max = sizeof(buffer) - idx -
// CHECK SIZES !
buffer[0] = cla;
buffer[1] = ins;
buffer[2] = p1;
buffer[3] = p2;
if(cbData)
{
buffer[idx++] = (BYTE) cbData;
RtlCopyMemory(buffer + idx, pbData, cbData);
idx += cbData;
}
if(!noLe && *cbResult)
buffer[idx++] = (BYTE) *cbResult;
return kull_m_arc_sendrecv(comm, buffer, idx, pbResult, cbResult);
}
BOOL CALLBACK kull_m_arcr_SendRecvDirect(const BYTE *pbData, const UINT16 cbData, BYTE *pbResult, UINT16 *cbResult, LPVOID suppdata)
{
BOOL status = FALSE;
BYTE buffer[ACR_MAX_LEN];
UINT16 cbOut = *cbResult + 2;
if(suppdata)
{
if(cbOut <= sizeof(buffer))
{
if(kull_m_acr_sendrecv_ins((PKULL_M_ACR_COMM) suppdata, 0xff, 0x00, 0x00, 0x00, pbData, cbData, buffer, &cbOut, TRUE))
{
if(cbOut >= 2)
{
if(*(PUINT16) (buffer + cbOut - 2) == 0x0090)
{
cbOut -= 2;
if(status = (cbOut <= *cbResult))
{
RtlCopyMemory(pbResult, buffer, cbOut);
*cbResult = cbOut;
}
else PRINT_ERROR(L"cbResult = %hu (data is %u)\n", *cbResult, cbOut);
}
else PRINT_ERROR(L"RET: %02x %02x\n", buffer[cbOut - 2], buffer[cbOut - 1]);
}
else PRINT_ERROR(L"cbRetBuffer = %hu (not long enough)\n", cbOut);
}
}
else PRINT_ERROR(L"cbOut = %hu (max is %hu)\n", cbOut, sizeof(buffer));
}
else PRINT_ERROR(L"No suppdata (ACR_COMM)\n");
return status;
}