Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Wednesday, June 28 2017 @ 09:20 PM CEST

Luhn (mod-10) formula

   

CodingLevel : beginner

OS : windows
Language : ASM

This formula is often use to check the validity of a credit card.
Think of it as a CRC checksum, it validates checksums of creditcards.

For more information regarding the algo, check out www.reversing.be/forum/viewtopic.php?p=2103

Now, let's get coding. I've written a DLL with function CheckCC() using fasm. The function accepts one parameter (buffer).



E.g.: if you'd like to check if credit card 1234-5678-9012-3456 is valid, you'd do:



.data
mybuffer db 1,2,3,4, 5,6,7,8, 9,0,1,2, 3,4,5,6
.code
push offset mybuffer
call CheckCC

That's it from the example. Now, lets take a look at the DLL function CheckCC()

format PE GUI 4.0 DLL

; Luhn formula credit card check algorithm
;
; written by BoR0
;
; 14-digit checkup:
; creditcard db 3,8,7,2,4, 6,3,1,6, 6,0,6,5,2, 0,0,0
;
; 16-digit checkup:
; creditcard db 4,0,1,3, 2,2,4,3, 5,5,2,1, 2,2,0,1

section '.data' data readable writeable

ccnum_watermark  db "written by",32
ccnum_watermark2 db "bor0, 2006", 0 ;)
ccnum_sum        dd ?

section '.code' code readable executable

        CheckCC:

        push    ebx
        push    esi
        push    edi

        mov     ebx, dword ptr esp+10h

        xor     esi, esi
        xor     edi, edi

        dec     edi
        sub     esi, 2

        mov     dword ptr ccnum_sum, 0

        cmp     dword ptr ccnum_watermark2, 30726f62h
        jne     cheat

        ; ллллллллллллллллллллллллллллллллллллллллллллллл
        ; here we sum odd numbers and even numbers
        @@:
        inc     edi
        add     esi, 2

        movzx   eax, byte ptr ebx+esi

        ; 1234 5678 9101 1121
        ; odd: 1 3 5 7 9 0 1 2 <- multiply by 2 and sum
        ; even: 2 4 6 8 1 1 1 1 <- just sum

        ; multiply all the digits in odd positions by 2
        xor     edx, edx
        mov     ecx, 2
        mul     ecx

        cmp     eax, 9
        jbe     @skip

        ;if any one is greater than 9 subtract 9 from it
        sub     eax, 9

        @skip:

        add     dword ptr ccnum_sum, eax ; odd number sum

        dec     esi
        movzx   eax, byte ptr ebx+esi
        inc     esi

        ; sum all the digits in even positions
        add     dword ptr ccnum_sum, eax ; even number sum

        cmp     edi, 7
        jne     @B
        ; ллллллллллллллллллллллллллллллллллллллллллллллл

        ; ллллллллллллллллллллллллллллллллллллллллллллллл
        ; expression ((sum / 10 + 1) * 10 - sum)%10
        movzx   eax, byte ptr ebx+15
        add     dword ptr ccnum_sum, eax

        mov     eax, dword ptr ccnum_sum
        mov     ecx, 10
        xor     edx, edx
        div     ecx ; sum/10

        inc     eax ; sum/10+1

        xor     edx, edx
        mul     ecx ; (sum/10+1)*10

        sub     eax, dword ptr ccnum_sum ; (sum/10+1)*10-sum

        xor     edx, edx
        div     ecx

        mov     dword ptr ccnum_sum, edx

        mov     eax, edx
        xor     edx, edx
        div     ecx ; ((sum / 10 + 1) * 10 - sum)%10

        pop     edi
        pop     esi
        pop     ebx

        ; check if our expression is a multiple of 10
        test    edx, edx
        jne     error
        ; ллллллллллллллллллллллллллллллллллллллллллллллл

        xor     eax, eax
        inc     eax
        retn    4 ; success!

        error:
        xor     eax, eax
        retn    4 ; error!

        cheat:
        xor     esp, esp

section '.edata' export data readable
dd 00h, 00h, 0
db 32h, 30h, 0, 0
db 01h, 00h, 0, 0, 01h, 00h, 0, 0, 01h, 00h, 0, 0, 28h, 30h, 0, 0
db 2Ch, 30h, 0, 0, 30h, 30h, 0, 0, 00h, 20h, 0, 0, 3Ch, 30h
dd 00h

db "ccdll.dll", 0, "CheckCC", 0

dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

section '.reloc' fixups data discardable


The export section is only exporting the function, don't let that confuse you. All the other stuff is well commented, I believe.

Here's an example of how I am doing the check-up using WINAPI console functions attachment

That's all, I think. Simple algo - simple tutorial :)
Credit card check-up is really easy done.

Greetings to all my friends, most the BiW reversing team




What's Related

Story Options

Luhn (mod-10) formula | 1 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
Luhn (mod-10) formula
Authored by: BoR0 on Tuesday, January 24 2006 @ 03:22 PM CET
The C version of the above ASM code (portable):
/*\
 *
 * Credit Card Check using the Luhn formula
 *
 * if success it returns 0, otherwise fails
 *
 *
 * written by BoR0, January 2006
 *
\*/

int checkcc(char *ccnum_digits) {

char ccnum_evendigit[16];
int sum=0; int j=0; int i=0;

for (i=0;i<8;i++,j+=2) {
ccnum_evendigit[i] = ccnum_digits[j]-48;
if (2*ccnum_evendigit[i] > 9) sum-=9;
sum += 2*ccnum_evendigit[i];
}

for (i=1;i<16;i+=2) sum += ccnum_digits[i]-48;

return ((sum / 10 + 1) * 10 - sum)%10;

}
 Copyright © 2017 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.06 seconds