2016-05-12 40 views
1

我試圖對Java Card做一些定時攻擊。我需要一種方法來測量發送命令和獲取答案。我使用的接口是winscard.h,語言是c++。 。我創建了一個包裝到winscard.h界面,以便讓我的工作更輕鬆。例如,發送一個APDU現在我使用這個代碼似乎工作。 基於this答案,我更新了我的代碼在C++中測量APDU命令到Java卡的時間的最佳方法

byte pbRecvBuffer[258]; 
long rv; 
if (this->sessionHandle >= this->internal.vSessions.size()) 
    throw new SmartCardException("There is no card inserted"); 
SCARD_IO_REQUEST pioRecvPci; 
pioRecvPci.dwProtocol = (this->internal.vSessions)[sessionHandle].dwActiveProtocol; 
pioRecvPci.cbPciLength = sizeof(pioRecvPci); 

LPSCARD_IO_REQUEST pioSendPci; 
if ((this->internal.vSessions)[sessionHandle].dwActiveProtocol == SCARD_PROTOCOL_T1) 
    pioSendPci = (LPSCARD_IO_REQUEST)SCARD_PCI_T1; 
else 
    pioSendPci = (LPSCARD_IO_REQUEST)SCARD_PCI_T0; 
word expected_length = 258;//apdu.getExpectedLen(); 
word send_length = apdu.getApduLength(); 
CardSession session = (this->internal.vSessions).operator[](sessionHandle); 
byte * data = const_cast<Apdu&>(apdu).getNonConstantData(); 
auto start = Timer::now(); 
rv = SCardTransmit(session.hCard, pioSendPci,data, 
    send_length, &pioRecvPci, pbRecvBuffer,&expected_length); 
auto end = Timer::now(); 
auto duration = (float)(end - start)/Timer::ticks(); 
return *new ApduResponse(pbRecvBuffer, expected_length,duration); 

class Timer 
{ 
public: 
static inline int ticks() 
{ 
    LARGE_INTEGER ticks; 
    QueryPerformanceFrequency(&ticks); 
    return ticks.LowPart; 
} 

static inline __int64 now() 
{ 
    struct { __int32 low, high; } counter; 

    __asm cpuid 
    __asm push EDX 
    __asm rdtsc 
    __asm mov counter.low, EAX 
    __asm mov counter.high, EDX 
    __asm pop EDX 
    __asm pop EAX 

    return *(__int64 *)(&counter); 
} 

};

我的代碼失敗,出現錯誤The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.。我的猜測是,我的英特爾處理器不支持rdtsc指令。我有英特爾Broadwell 5500U。 。我正在尋找一種合適的方式來做這種測量,並最終得到更準確的答案。

+1

可能的[在Linux/Windows上測量CPU時間和掛鐘時間?]的重複(http://stackoverflow.com/questions/17432502/how-can-i-measure-cpu-time-and -wall-clock-time-on-both-linux-windows) –

+0

@MichaelRoland更新了代碼,更清楚地解釋了我的問題 – Marga

回答

4

您提供

ESP的值未正確保存跨函數調用中的錯誤消息。這個 通常是調用一個函數聲明的函數的結果,其中一個調用 約定,其中函數指針聲明的約定爲不同的調用 。

指示您調用的內聯彙編函數中存在錯誤。假設在調用它時使用默認調用約定,它基本上是有缺陷的:cpuid銷燬ebx,這是一個被調用者保存的寄存器。此外,它只將一個參數壓入堆棧,並彈出兩個參數:第二個彈出窗口實際上(最有可能)是該函數的返回地址,或基本指針保存爲堆棧框架的一部分。因此,函數在調用ret時失敗,因爲它沒有有效的地址返回,或者運行時檢測到新值esp(它從函數開頭的值恢復)僅僅是無效的。這與您使用的CPU無關,因爲所有x86 CPU都支持RDTSC - 儘管它使用的基準時鐘可能會因CPU的當前速度狀態而有所不同,這就是爲什麼不直接使用該指令的原因,以及操作系統設施應該受到青睞,因爲它們爲不同的步進指令的不同實施提供了補償。

看你如何使用C++ 11 - 通過使用auto來判斷 - 使用std::chrono來測量時間間隔。如果由於某種原因無法使用,請使用您的操作系統提供的工具(這看起來像Windows,因此QueryPerformanceCounter可能是使用的工具)。如果這仍然不能滿足您的需求,您可以使用__rdtsc內部函數生成rdtsc,而不用擔心內聯彙編。