IDA 中的IDC腳本編寫筆記


交互式反匯編器,簡稱為IDA。是目前最好的反匯編工具,常用於0day挖掘,逆向等領域,網上關於IDC腳本的說明少之又少,這里我就把我的一些常用使用技巧分享一下,在IDA中按下【shift + F2】可調出腳本編輯器,可以簡單的學習一下IDA IDC腳本的編寫與使用,IDC腳本借鑒的C語言的語法,所以其看起來很像。

簡單的IF語句

#include <idc.idc>

static main()
{
    auto CurrAddress = ScreenEA(); 
    if(CurrAddress == 0x401161)
    {
       Message("程序OEP => 0x%x \n",CurrAddress);
    }
    else
    {
      Message("沒有扎到OEP \n");
    }
}

for語句

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    // NextHead 在currEA開始的位置尋找下一條指令的地址
    for(currEA = funcStart; currEA != -1; currEA=NextHead(currEA,funcEnd))
    {
        Message("--> %8x \n",currEA);
    }
}

while語句實現

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    while(currEA != BADADDR)
    {
        Message("--> %x \n",currEA);
        currEA = NextHead(currEA,funcEnd);
    }
}

idc 函數

#include <idc.idc>

// 定義一個函數
static OutPutAddress(MyString)
{
    auto currAddress;
    currAddress = ScreenEA();
    Message("%d \n",MyString);
    return currAddress;
}

static main()
{
    auto ret = OutPutAddress(123);
    Message("%x \n",ret);
    
}

idc 獲取函數名

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    while(currEA != BADADDR)
    {
        Message("--> %x name: %s \n",currEA,GetFunctionName(currEA));
        currEA = NextHead(currEA,funcEnd);
    }
}

idc 枚舉所有函數

#include <idc.idc>

static main()
{
    auto currAddr,func,endSeg,funcName,counter;
    
    currAddr = ScreenEA();
    func = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("%x --> %x \n",func,endSeg);
    
    counter = 0;
    
    while(func != BADADDR && func < endSeg)
    {
        funcName = GetFunctionName(func);
        if(funcName != " ")
        {
            Message("%x --> %s \n",func,funcName);
            counter++;
        }
        func = NextFunction(func);
    }
     
}

枚舉指定函數並輸出

#include <idc.idc>

static main()
{
    auto currAddr,func,endSeg,funcName,counter;
    
    currAddr = ScreenEA();
    func = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("%x --> %x \n",func,endSeg);
    
    counter = 0;
    
    while(func != BADADDR && func < endSeg)
    {
        funcName = GetFunctionName(func);
        if(funcName != " ")
        {
        
            if(funcName == "__lock")
            {
                Message("%x --> %s \n",func,funcName);
            }
            
            counter++;
        }
        func = NextFunction(func);
    }
}

尋找特殊指令,並高亮顯示

#include <idc.idc>
static main(void)
{
    auto head, op;
    head = NextHead(0x00000000, 0xFFFFFFFF);
    while ( head != BADADDR )
    {
        op = GetMnem(head);
        Message("%x %s \n",head,op);

        
        if ( op == "jmp" || op == "call" )
            SetColor(head, CIC_ITEM, 0x010187);
            
        if (op == "xor")
            SetColor(head, CIC_ITEM, 0x010198);
        head = NextHead(head, 0xFFFFFFFF);
    }
}

ida dump 將函數dump到本地。

#include <idc.idc>

static getFuncName(ea)
{
    auto funcName = get_func_name(ea);
		
    auto dm = demangle_name(funcName, get_inf_attr(INF_LONG_DN));
    if(dm != 0)
    {
        funcName = dm;
    }
    return funcName;
}

static functionDump(ea)
{
    auto funcName = 0;
    auto end = 0x0;
    auto file_open = get_idb_path()[0:-4] + "_dump.log";
    auto stream = fopen(file_open, "w");
    auto peekAhead;

    while( ea != BADADDR )
    {
        ea = NextFunction(ea);		
        peekAhead = NextFunction(ea);
        end = FindFuncEnd(ea);	
        funcName = getFuncName(ea);

        if(peekAhead == BADADDR)
        {
            fprintf(stream, "{ 0x%X, 0x%X, \"%s\" }\n", ea, end, funcName);
            ea = peekAhead;
            continue;
        }
            end = peekAhead - 1;		
            fprintf(stream, "{ 0x%X, 0x%X, \"%s\" }\n", ea, end,funcName);
    }
        fclose(stream);
}

static main()
{
    functionDump(0x40000);
}

全量反匯編:

#include <idc.idc>

static main(void)
{


    auto decode = 0x401000;
    auto xref;
    
    for(xref = RfirstB(decode); xref != BADADDR; xref = RnextB(decode,xref))
    {
         Message("xref: %x\n",xref);
    
    auto i = 0;
      auto inst = xref;
    auto op;
        
        
       while((i < 100) )
       {
        inst = FindCode(inst,0x00); // flag set to backwards
      op = GetDisasm(inst); // get
      
      Message("%x --> %s \n",inst,op);
        i++;
       }
    } 
}

查找特定指令片段

#include <idc.idc>

static main()
{
    auto currAddr,startSeg,endSeg;
    
    currAddr = ScreenEA();
    startSeg = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("OEP = %x 起始地址: %x 結束地址: %x \n",currAddr,startSeg,endSeg);
    
    while(startSeg < endSeg)
    {
        auto op = GetDisasm(startSeg);
        
        // 查找第一條指令
        if(strstr(op,"push    esi")==0)
        {
            startSeg++;
            op = GetDisasm(startSeg);
            if(strstr(op,"push    edi"))
            {
                Message("特征: %x \n",startSeg-1);
            }
        }
        startSeg++;
    }
}

全局數組操作: 數組是全局的,並寫入數據庫,白嫖完了,一定得釋放。

#include <idc.idc>

static main()
{
    // 創建數組元素
    auto array_ptr = CreateArray("array");
    // 獲取數組指針
    auto ptr = GetArrayId("array");
    
    Message("獲取到的操作指針: %x \n",ptr);
    
    // 設置兩個字符串變量
    SetArrayString(ptr,0,"hello");
    SetArrayString(ptr,1,"lyshark");
    
    // 設置兩個整數變量
    SetArrayLong(ptr,2,100);
    SetArrayLong(ptr,3,200);
    
    // 如果提取字符串使用 AR_STR 標記 ,提取整數使用 AR_LONG
    auto st = GetArrayElement(AR_STR,ptr,0);
    auto st1 = GetArrayElement(AR_STR,ptr,1);
    Message("提取字符串變量: %s %s !\n",st,st1);
    
    auto lo = GetArrayElement(AR_LONG,ptr,2);
    Message("提取整數變量: %d \n",lo);
    
    // 刪除數組的0號元素
    DelArrayElement(AR_STR,ptr,0);
    // 注銷整個數組
    DeleteArray(ptr);
}

字符串處理函數:

#include <idc.idc>

static main()
{
    // 格式化字符串,類似於sprintf
    auto name = form("hello %s","lyshark");
    Message("格式化后的內容: %s \n",name);
    
    Message("十六進制轉為整數: %d \n",xtol("0x41"));
    Message("十進制100轉為八進制: %d \n",ltoa(100,8));
    Message("十進制100轉換二進制: %d \n",ltoa(100,2));
    Message("字符A的ASCII: %d \n",ord("A"));
    Message("計算字符串長度: %d \n",strlen("hello lyshark"));
    
    // 在著字符串中尋找子串
    auto main = "hello lyshark";
    auto sub = "lyshark";
    Message("尋找子串: %d \n",strstr(main,sub));
}

反匯編函數:

#include <idc.idc>

static main()
{
// 索索特征碼
    auto code = FindBinary(0x401020,1,"55 8B EC");
    Message("%x \n",code);


    // 反匯反匯編代碼
    code = GetDisasm(0x401000);
    Message("%s \n",code);
    
    // 反匯 位於地址處的指令
    code = GetMnem(0x401000);
    Message("%s \n",code);
    
    // 反匯opcode
    code = GetOpnd(0x401070,0);
    Message("%s \n",code);
}

枚舉函數(枚舉棧幀)

#include <idc.idc>

static main()
{
    auto addr,args,end,locals,frame,firstArg,name,ret;
    
    for(addr = NextFunction(addr); addr != BADADDR; addr = NextFunction(addr))
    {
        name = Name(addr);
        end = GetFunctionAttr(addr,FUNCATTR_END);
        locals = GetFunctionAttr(addr,FUNCATTR_FRSIZE);
        // 得到棧幀大小
        frame = GetFrame(addr);
        // 棧中保存返回地址偏移量
        ret = GetMemberOffset(frame," r");
        if(ret == -1)continue;
        firstArg = ret +4;
        args = GetStrucSize(frame) - firstArg;
        Message("函數: %s 開始: 0x%x 結束: 0x%x 大小: %d bytes 棧幀: %d bytes (%d args) \n",name,addr,end,locals,args,args/4);
    }
}

檢索交叉引用(全部):

#include <idc.idc>

static main()
{
    auto func,end,target,inst,name,flags,xref;
    
    flags = SEARCH_DOWN | SEARCH_NEXT;
    
    func = GetFunctionAttr(ScreenEA(),FUNCATTR_START);
    
    if(func != -1)
    {
        name =Name(func);
        end = GetFunctionAttr(func,FUNCATTR_END);
        for(inst = func;inst < end; inst = FindCode(inst,flags))
        {
            for(target = Rfirst(inst);target != BADADDR; target = Rnext(inst,target))
            {
                xref = XrefType();
                if(xref == fl_CN || xref == fl_CF)
                {
                    Message("%s call -> %sfrom --> %x \n",name,Name(target),inst);
                }
            }
        }
    }
}


if

#include <idc.idc>

static main()
{
    auto CurrAddress = ScreenEA(); 
    if(CurrAddress == 0x401161)
    {
       Message("程序OEP => 0x%x \n",CurrAddress);
    }
    else
    {
      Message("沒有扎到OEP \n");
    }
}

for

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    // NextHead 在currEA開始的位置尋找下一條指令的地址
    for(currEA = funcStart; currEA != -1; currEA=NextHead(currEA,funcEnd))
    {
        Message("--> %8x \n",currEA);
    }
}

while語句實現

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    while(currEA != BADADDR)
    {
        Message("--> %x \n",currEA);
        currEA = NextHead(currEA,funcEnd);
    }
}

idc 函數

#include <idc.idc>

// 定義一個函數
static OutPutAddress(MyString)
{
    auto currAddress;
    currAddress = ScreenEA();
    Message("%d \n",MyString);
    return currAddress;
}

static main()
{
    auto ret = OutPutAddress(123);
    Message("%x \n",ret);
    
}

idc 獲取函數名

#include <idc.idc>

static main()
{
    auto origEA,currEA,funcStart,funcEnd;
    
    origEA = ScreenEA();
    // origEA = OEP 如果origEA 不在函數內則返回-1
    funcStart = GetFunctionAttr(origEA,FUNCATTR_START);
    
    funcEnd = GetFunctionAttr(origEA,FUNCATTR_END);
    
    //Message("OEP: %x 起始地址: %x --> 結束地址: %x \n",origEA,funcStart,funcEnd);
    
    while(currEA != BADADDR)
    {
        Message("--> %x name: %s \n",currEA,GetFunctionName(currEA));
        
        
        
        currEA = NextHead(currEA,funcEnd);
    }
}

idc 枚舉所有函數

#include <idc.idc>

static main()
{
    auto currAddr,func,endSeg,funcName,counter;
    
    currAddr = ScreenEA();
    func = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("%x --> %x \n",func,endSeg);
    
    counter = 0;
    
    while(func != BADADDR && func < endSeg)
    {
        funcName = GetFunctionName(func);
        if(funcName != " ")
        {
            Message("%x --> %s \n",func,funcName);
            counter++;
        }
        func = NextFunction(func);
    }
     
}
#include <idc.idc>

static main()
{
    auto currAddr,func,endSeg,funcName,counter;
    
    currAddr = ScreenEA();
    func = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("%x --> %x \n",func,endSeg);
    
    counter = 0;
    
    while(func != BADADDR && func < endSeg)
    {
        funcName = GetFunctionName(func);
        if(funcName != " ")
        {
        
            if(funcName == "__lock")
            {
                Message("%x --> %s \n",func,funcName);
            }
            
            counter++;
        }
        func = NextFunction(func);
    }
     
}

尋找特殊指令,並高亮顯示

#include <idc.idc>
static main(void)
{
    auto head, op;
    head = NextHead(0x00000000, 0xFFFFFFFF);
    while ( head != BADADDR )
    {
        op = GetMnem(head);
        Message("%x %s \n",head,op);

        
        if ( op == "jmp" || op == "call" )
            SetColor(head, CIC_ITEM, 0x010187);

        head = NextHead(head, 0xFFFFFFFF);
    }
}

ida dump

#include <idc.idc>

static getFuncName(ea)
{
    auto funcName = get_func_name(ea);
		
    auto dm = demangle_name(funcName, get_inf_attr(INF_LONG_DN));
    if(dm != 0)
    {
        funcName = dm;
    }
    return funcName;
}

static functionDump(ea)
{
    auto funcName = 0;
    auto end = 0x0;
    auto file_open = get_idb_path()[0:-4] + "_dump.log";
    auto stream = fopen(file_open, "w");
    auto peekAhead;


    while( ea != BADADDR )
    {
        ea = NextFunction(ea);		
        peekAhead = NextFunction(ea);
        end = FindFuncEnd(ea);	
        funcName = getFuncName(ea);

        if(peekAhead == BADADDR)
        {
            fprintf(stream, "{ 0x%X, 0x%X, \"%s\" }\n", ea, end, funcName);
            ea = peekAhead;
            continue;
        }
            end = peekAhead - 1;		
            fprintf(stream, "{ 0x%X, 0x%X, \"%s\" }\n", ea, end,funcName);
    }
        fclose(stream);
}

static main()
{
    functionDump(0x40000);
}

查找特定指令片段

#include <idc.idc>

static main()
{
    auto currAddr,startSeg,endSeg;
    
	Jump(0x0401000);                      // 光標跳轉到起始位置
    currAddr = ScreenEA();                // 反回當前光標所在地址
    startSeg = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("OEP = %x 起始地址: %x 結束地址: %x \n",currAddr,startSeg,endSeg);
    
    while(startSeg < endSeg)
    {
        auto op = GetDisasm(startSeg);
        
        // 查找第一條指令
        if(strstr(op,"push    esi")==0)
        {
            startSeg++;
            op = GetDisasm(startSeg);
            if(strstr(op,"push    edi")==0)
            {
                Message("特征: %x \n",startSeg-1);
            }
        }
        startSeg++;
    }
}

關鍵字段定位:

#include <idc.idc>

static main()
{
    auto currAddr,startSeg,endSeg;
    
    auto array_ptr = CreateArray("array");
    auto ptr = GetArrayId("array");

    SetArrayString(ptr,0,"push    ebp");
    SetArrayString(ptr,1,"mov     ebp, esp");
    
    
    Jump(0x0401000);                      // 光標跳轉到起始位置
    currAddr = ScreenEA();                // 反回當前光標所在地址
    startSeg = SegStart(currAddr);
    endSeg = SegEnd(currAddr);
    
    Message("OEP = %x 起始地址: %x 結束地址: %x \n",currAddr,startSeg,endSeg);
    
    while(startSeg < endSeg)
    {
        auto x = 0;
        auto count=0;
        
        for(x=0;x<2;x++)
        {
            auto op = GetDisasm(startSeg);
            auto st = GetArrayElement(AR_STR,ptr,x);
            
            if(strstr(op,st) == 0)
            {
                count = count +1;
                if(count == 2)
                {
                    msg("匹配地址: %x \n",startSeg--);
                }
            }
            startSeg++;
        }
        
    }
    DeleteArray(ptr);
}

全局數組操作: 數組是全局的,並寫入數據庫,白嫖完了,一定得釋放。

#include <idc.idc>

static main()
{
    // 創建數組元素
    auto array_ptr = CreateArray("array");
    // 獲取數組指針
    auto ptr = GetArrayId("array");
    
    Message("獲取到的操作指針: %x \n",ptr);
    
    // 設置兩個字符串變量
    SetArrayString(ptr,0,"hello");
    SetArrayString(ptr,1,"lyshark");
    
    // 設置兩個整數變量
    SetArrayLong(ptr,2,100);
    SetArrayLong(ptr,3,200);
    
    // 如果提取字符串使用 AR_STR 標記 ,提取整數使用 AR_LONG
    auto st = GetArrayElement(AR_STR,ptr,0);
    auto st1 = GetArrayElement(AR_STR,ptr,1);
    Message("提取字符串變量: %s %s !\n",st,st1);
    
    auto lo = GetArrayElement(AR_LONG,ptr,2);
    Message("提取整數變量: %d \n",lo);
    
    // 刪除數組的0號元素
    DelArrayElement(AR_STR,ptr,0);
    // 注銷整個數組
    DeleteArray(ptr);
}

字符串處理函數:

#include <idc.idc>

static main()
{
    // 格式化字符串,類似於sprintf
    auto name = form("hello %s","lyshark");
    Message("格式化后的內容: %s \n",name);
    
    Message("十六進制轉為整數: %d \n",xtol("0x41"));
    Message("十進制100轉為八進制: %d \n",ltoa(100,8));
    Message("十進制100轉換二進制: %d \n",ltoa(100,2));
    Message("字符A的ASCII: %d \n",ord("A"));
    Message("計算字符串長度: %d \n",strlen("hello lyshark"));
    
    // 在著字符串中尋找子串
    auto main = "hello lyshark";
    auto sub = "lyshark";
    Message("尋找子串: %d \n",strstr(main,sub));
}

反匯編函數:

#include <idc.idc>

static main()
{
// 索索特征碼
    auto code = FindBinary(0x401020,1,"55 8B EC");
    Message("%x \n",code);


    // 反匯反匯編代碼
    code = GetDisasm(0x401000);
    Message("%s \n",code);
    
    // 反匯 位於地址處的指令
    code = GetMnem(0x401000);
    Message("%s \n",code);
    
    // 反匯opcode
    code = GetOpnd(0x401070,0);
    Message("%s \n",code);
    

}

枚舉函數:

#include <idc.idc>

static main()
{
    auto addr,args,end,locals,frame,firstArg,name,ret;
    
    for(addr = NextFunction(addr); addr != BADADDR; addr = NextFunction(addr))
    {
        name = Name(addr);
        end = GetFunctionAttr(addr,FUNCATTR_END);
        locals = GetFunctionAttr(addr,FUNCATTR_FRSIZE);
        // 得到棧幀大小
        frame = GetFrame(addr);
        // 棧中保存返回地址偏移量
        ret = GetMemberOffset(frame," r");
        if(ret == -1)continue;
        firstArg = ret +4;
        args = GetStrucSize(frame) - firstArg;
        Message("函數: %s 開始: 0x%x 結束: 0x%x 大小: %d bytes 棧幀: %d bytes (%d args) \n",name,addr,end,locals,args,args/4);
    }
}

枚舉指令: 測試

#include <idc.idc>

static main()
{
    auto func,end,count,inst;
    func = GetFunctionAttr(ScreenEA(),FUNCATTR_START);
    
    if(func != -1)
    {
        end = GetFunctionAttr(func,FUNCATTR_END);
        count =0;
        inst = func;
        
        while(inst < end)
        {
            count ++;
            inst = FindCode(inst,SEARCH_DOWN | SEARCH_NEXT);
        }
        Message("%s --> %d \n",Name(func),count);
    }
}

檢索交叉引用(全部):

#include <idc.idc>

static main()
{
    auto func,end,target,inst,name,flags,xref;
    
    flags = SEARCH_DOWN | SEARCH_NEXT;
    
    func = GetFunctionAttr(ScreenEA(),FUNCATTR_START);
    
    if(func != -1)
    {
        name =Name(func);
        end = GetFunctionAttr(func,FUNCATTR_END);
        for(inst = func;inst < end; inst = FindCode(inst,flags))
        {
            for(target = Rfirst(inst);target != BADADDR; target = Rnext(inst,target))
            {
                xref = XrefType();
                if(xref == fl_CN || xref == fl_CF)
                {
                    Message("%s call -> %sfrom --> %x \n",name,Name(target),inst);
                }
            }
        }
    }
}

枚舉指定交叉引用函數:

#include <idc.idc>

static FindFunction(bad_func)
{
    auto func,addr,xref,source;
    
    func = LocByName(bad_func);
    if(func == BADADDR)
    {
        Message("error \n");
    }
    else
    {
        for(addr = RfirstB(func);addr != BADADDR; addr = RnextB(func,addr))
        {
            xref = XrefType();
            if(xref == fl_CN || xref == fl_CF)
            {
                source = GetFunctionName(addr);
                Message("%s call => %0x in %s \n",bad_func,addr,source);
            }
        }
    }  
}

static main()
{
    FindFunction("LoadString");
}
#include <idc.idc>

static main()
{
    auto inpt_count,i,ord,addr,name,purged,file,fd;
    
    file = AskFile(1,"*.idt","select idt save file");
    fd = fopen(file,"w");
    
    inpt_count = GetEntryPointQty();
    fprintf(fd,"Name = %s \n",GetInputFile());
    fprintf(fd,"inpt_count = %x \n",inpt_count);
    for(i=0;i<inpt_count;i++)
    {
        ord = GetEntryOrdinal(i);
        if(ord == 0) continue;
        addr = GetEntryPoint(ord);
        if(ord == addr)
        {
            continue;
        }
        
        name = Name(addr);
        fprintf(fd,"%d Name = %s \n",ord,name);
        purged = GetFunctionAttr(addr,FUNCATTR_ARGSIZE);
        if(purged > 0)
        {
        fprintf(fd,"pascal = %d ",purged);
        }
        fprintf(fd,"\n");
    } 
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM