//signatures match void sigMatch(range range, Mem *mem, int pageSize, int dsmPages[], int *match_time) { int i; struct timeval earlier; struct timeval later; //begin match int osNumber = initDb(); extern fingerprint fingerprints[FINGERPRINT_NO]; if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } int availableOs[FINGERPRINT_NO], matchCounts[FINGERPRINT_NO]; for (i = 0; i < FINGERPRINT_NO; i++) { availableOs[i] = 1; matchCounts[i] = 0; } unsigned startVirtualAddr = range.start; for (; startVirtualAddr <= range.end; startVirtualAddr += 0x1000) { unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, startVirtualAddr); if (pAddr == -1 || pAddr > mem->mem_size) continue; int pageIndex = pAddr / pageSize; if (dsmPages[pageIndex] == 1) { int offset = (startVirtualAddr - range.start) / 4096; void *startAdress = (void*) ((unsigned) mem->mem + pageIndex * pageSize); unsigned char md5digest[16]; MDMem(startAdress, pageSize, md5digest); // printf("%x ", vaddr); //print vaddr MDPrint(md5digest); printf("\n"); int ret = matchByIndex(osNumber, md5digest, offset, availableOs, matchCounts); // if(ret ==1) } } int maxIndex = -1; int maxMatch = 0; for (i = 0; i < FINGERPRINT_NO; i++) { if (matchCounts[i] > maxMatch) { maxIndex = i; maxMatch = matchCounts[i]; } } if (maxMatch > 0) printf("Os is %s, match count is %d\n", fingerprints[maxIndex].osVersion, maxMatch); else puts("Unknown OS!"); if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } *match_time = timeval_diff(NULL, &later, &earlier) / 1000; printf("match time cost is %d milliseconds\n", *match_time); }
void fsl_buffer_pool_fill(struct packet_pool_cfg *pool_cfg) { int err; int loop; struct bman_pool *p; struct packet_pool_cfg *bp = pool_cfg; for (; bp->bpid != -1; bp++) { struct bm_buffer bufs[8]; int num_bufs = 0; p = helper_pool[bp->bpid]; err = 0; /* Drain the pool of anything already in it. */ if (bp->num > 0) { do { if (err != 1) err = bman_acquire(p, bufs, 8, 0); if (err < 8) err = bman_acquire(p, bufs, 1, 0); if (err > 0) num_bufs += err; } while (err > 0); } if (num_bufs) TRACE("warn: drained %u bufs from BPID %d\n", num_bufs, bp->bpid); /* Fill the pool */ for (num_bufs = 0; num_bufs < bp->num;) { int rel = (bp->num - num_bufs) > 8 ? 8 : (bp->num - num_bufs); for (loop = 0; loop < rel; loop++) { void *ptr = DMA_MEM_ALLOC(L1_CACHE_BYTES, bp->size); if (!ptr) { TRACE("error: no space for bpid %d\n", bp->bpid); return; } bm_buffer_set64(&bufs[loop], vtop(ptr)); } do { err = bman_release(p, bufs, rel, 0); } while (err == -EBUSY); if (err) TRACE("error: release failure\n"); num_bufs += rel; } TRACE("Release %u bufs to BPID %d\n", num_bufs, bp->bpid); } }
/*determine whether a value is a valid non-empty kernel point */ int isKernelAddress(unsigned vaddr, Mem * mem) { unsigned kernleStartAddr; kernleStartAddr = 0xc0000000; if (vaddr > kernleStartAddr) { unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, vaddr); if (pAddr > 0 && pAddr < mem->mem_size) return 1; } return 0; }
void fsl_buffer_free(void *bd, u32 pool_id) { int ret; struct bm_buffer buf; buf.addr = vtop(bd); retry: ret = bman_release(helper_pool[pool_id], &buf, 1, 0); if (unlikely(ret == -EBUSY)) goto retry; else if (ret) TRACE("bman release failure, ret %d\n", ret); }
/*determine whether a value is a valid non-empty kernel point */ int isKernelAddress(unsigned vaddr, char *mem, unsigned mem_size, unsigned pgd, int isWindows) { unsigned kernleStartAddr; if (isWindows) kernleStartAddr = 0x80000000; else kernleStartAddr = 0xc0000000; if (vaddr > kernleStartAddr) { unsigned pAddr = vtop(mem, mem_size, pgd, vaddr); if (pAddr > 0 && pAddr < mem_size) return 1; } return 0; }
/* * kern_mem() * Create a segment which views a range of kernel memory * * Mostly used to provide a view of a new client's capabilities. */ struct seg * kern_mem(void *vaddr, uint len) { struct seg *s; ulong pgstart, pgend; struct pview *pv; int x; struct pset *ps; extern struct pset *physmem_pset(); /* * Allocate a new segment, fill in some fields. Use the * pset layer to create a physmem-type page set on which * we build our view. */ s = MALLOC(sizeof(struct seg), MT_SEG); s->s_off = (ulong)vaddr & (NBPG-1); s->s_len = len; pv = &s->s_pview; pgstart = btop(vaddr); pgend = btop((char *)vaddr + len - 1); pv->p_len = pgend-pgstart+1; pv->p_off = 0; ps = pv->p_set = physmem_pset(0, pv->p_len); ref_pset(ps); pv->p_prot = PROT_RO; /* * Fill in the slots of the physmem pset with the actual * page numbers for each page in the vaddr range. */ for (x = 0; x < pv->p_len; ++x) { struct perpage *pp; pp = find_pp(ps, x); pp->pp_pfn = btop(vtop((char *)vaddr + ptob(x))); } return(s); }
/* traverse page by page */ void findReadOnlyPages(Mem * mem) { int i; int pageSize = 4 * 1024; //4k int totalPageNumber = mem->mem_size / (4 * 1024); //assume that every page has 4k int calledPages[totalPageNumber]; int dsmPages[totalPageNumber]; //record virtual address unsigned virtualAddrs[totalPageNumber]; for (i = 0; i < totalPageNumber; i++) { calledPages[i] = 0; dsmPages[i] = 0; virtualAddrs[i] = 0; } unsigned cr3Pages[100]; for (i = 0; i < 100; i++) { cr3Pages[i] = 0; } //start address unsigned startVirtualAddr = 0x80000000; //step 1. kdi int kdi_time =0; int allPages=0; int cluster_index= kdi(startVirtualAddr, mem,pageSize,cr3Pages, &kdi_time, &allPages); //step 2. signature generation struct timeval earlier; struct timeval later; if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } int cr3ClusterNo = 0; int cr3PageNo = 0; ranges[0].end = 0; //find the cluster which has max cr3 number int maxcr3Index = findClusterHasMaxCr3(cluster_index, clusters, cr3Pages, &cr3ClusterNo); if (maxcr3Index == -1) { puts("Cannot find clusters have cr3."); // return ; } unsigned codePageNo = 0; newstart = 1; unsigned vAddr; for (vAddr = clusters[maxcr3Index].start; vAddr < clusters[maxcr3Index].end; vAddr += 0x1000) { cr3PageNo++; unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, vAddr); if (vAddr == out_pc) code_init(mem, vAddr, pageSize, dsmPages, virtualAddrs, 1, calledPages, &codePageNo); else code_init(mem, vAddr, pageSize, dsmPages, virtualAddrs, 0, calledPages, &codePageNo); } ranges[range_index].end = clusters[maxcr3Index].end; ranges[range_index].len = ranges[range_index].end - ranges[range_index].start; //find the max range int max_len = 0, max_index = 0; for (i = 1; i <= range_index; i++) { if (containKernelAddresForRange(ranges[i], cr3Pages) != 0) { continue; } printf("start:%x, end:%x: len:%x kernel\n", ranges[i].start, ranges[i].end, ranges[i].len); if (ranges[i].len > max_len) { max_index = i; max_len = ranges[i].len; } } unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, ranges[max_index].start); int pageIndex = pAddr / pageSize; char *page = (char*) ((unsigned) mem->mem + pAddr); code_preprocess(mem, page, ranges[max_index].len, 0x1000, ranges + max_index, dsmPages + pageIndex); printf("step2: cluster: %d\n", range_index); //print md5 of pages that can be disassembled startVirtualAddr = ranges[max_index].start; unsigned disasPageNo = 0; unsigned totalPageNo = 0; for (; startVirtualAddr <= ranges[max_index].end; startVirtualAddr += 0x1000) { totalPageNo++; unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, startVirtualAddr); if (pAddr == -1 || pAddr > mem->mem_size) continue; int pageIndex = pAddr / pageSize; if (dsmPages[pageIndex] == 1) { unsigned offset = startVirtualAddr - ranges[max_index].start; void *startAdress = (void*) ((unsigned) mem->mem + pageIndex * pageSize); genMd5WithOffset(startAdress, pageSize, startVirtualAddr, offset); disasPageNo++; } } if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } int sigGen_time = timeval_diff(NULL, &later, &earlier) / 1000; printf("step2: time cost is %d milliseconds\n", sigGen_time); float byerate = (float) ranges[max_index].disasBytes / (4096 * disasPageNo); printf("Success pages: %u/%u disassembled bytes rate: %f, page rate: %f\n", disasPageNo, totalPageNo, (float) ranges[max_index].disasBytes / (4096 * disasPageNo), (float) disasPageNo / totalPageNo); //record data; recordData(allPages, cluster_index, cr3ClusterNo, cr3PageNo, totalPageNo, disasPageNo, byerate); //begin match int match_time = 0; sigMatch(ranges[max_index], mem, pageSize, dsmPages, &match_time); //record performance recordPerformance(kdi_time, sigGen_time, match_time); return; }
/* determine version of OS by mem * 1.To get signature of multiply versions of os, which is the md5 of kernel code * 2.Compared by a decision tree. * 3.Done!*/ void determineOsVersion(Mem * mem) { int i; int pageSize = 4 * 1024; //4k int totalPageNumber = mem->mem_size / (4 * 1024); //assume that every page has 4k unsigned codePageNo = 0; //record when two page have different page index and the same sharp int calledPages[totalPageNumber]; int dsmPages[totalPageNumber]; //record virtual address unsigned virtualAddrs[totalPageNumber]; for (i = 0; i < totalPageNumber; i++) { calledPages[i] = 0; dsmPages[i] = 0; virtualAddrs[i] = 0; } //start address unsigned startVirtualAddr = KERNEL_START_ADDRESS; //with dissemble or not int withDissemble = 1; int cr3PageIndex = 0; unsigned cr3Pages[20]; for (i = 0; i < 20; i++) { cr3Pages[i] = 0; } struct timeval earlier; struct timeval later; if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } //generate step 1 clusters clusters[0].end = 0; int pre_rw = -1; //read or write int pre_us = -1; //use or system int pre_g = -1; //global, no move out of TLB int pre_ps = -1; //page size unsigned cluster_index = 0; newstart = 1; unsigned vAddr = startVirtualAddr; for (; vAddr > KERNEL_START_ADDRESS - 1; vAddr += 0x1000) { //printf("startvirtual %x:\n",startVirtualAddr); int rw = 0; //read or write int us = 0; //use or system int g = 0; //global, no move out of TLB int ps = 0; //page size 4M or 4k unsigned pAddr = vtopPageProperty(mem->mem, mem->mem_size, mem->pgd, vAddr, &rw, &us, &g, &ps); //if PHYSICAL ADDRESS is not VALID, then start a new cluster if (pAddr < 0 || pAddr > mem->mem_size || us != 0 || g != 256) { if (newstart == 0) { clusters[cluster_index].end = vAddr - 1; //printf("err address end is %x %x\n", vAddr, ranges[range_index].end); newstart = 1; } continue; } //if any property changes, then start a new cluster if (rw != pre_rw || us != pre_us || g != pre_g || ps != pre_ps) { if (newstart == 0) { clusters[cluster_index].end = vAddr - 1; //printf("property change end is %x %x\n", vAddr, ranges[range_index].end); newstart = 1; } } //update pre properties pre_rw = rw; pre_us = us; pre_g = g; pre_ps = ps; //collect pages with continuous properties; if (newstart) { clusters[++cluster_index].start = vAddr; clusters[cluster_index].end = vAddr + pageSize - 1; newstart = 0; } else clusters[cluster_index].end = vAddr + pageSize - 1; } if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } printf("step1, cluster: %d,time cost is %d milliseconds\n", cluster_index, timeval_diff(NULL, &later, &earlier) / 1000); //step2. kernel code page clusters with cr3 if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } unsigned startVirtual = startVirtualAddr; for (; startVirtual > startVirtualAddr - 1; startVirtual += 0x1000) { // for (; startVirtual < 0x818f0000; startVirtual += 0x1000) { unsigned vAddr = startVirtual; int rw = 0; //read or write int us = 0; //use or system int g = 0; //global(no move out of TLB) or not global int ps = 0; //page size unsigned pAddr = vtopPageProperty(mem->mem, mem->mem_size, mem->pgd, vAddr, &rw, &us, &g, &ps); // IS PHYSICAL ADDRESS VALID? if (pAddr == -1 || pAddr > mem->mem_size) continue; //collect pages which are system access, and global pages if (us == 0 && g == 256) { // printf("r only page %x\n", vAddr); if (find_kernel(mem, vAddr, pageSize) == 0) { //record kernel address cr3Pages[cr3PageIndex++] = vAddr; printf("kernel start at %x\n", vAddr); } } } if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } printf("step2 time cost is %d milliseconds\n", timeval_diff(NULL, &later, &earlier) / 1000); //step 3. clusters if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } int cr3PagesNo = 0; ranges[0].end = 0; newstart = 1; for (i = 1; i <= cluster_index; i++) { //:w printf("%x %x\n", clusters[i].start, clusters[i].end); if (containKernelAddres(clusters[i], cr3Pages) == -1) { continue; } cr3PagesNo++; unsigned vAddr = clusters[i].start; // printf("%x %x\n", clusters[i].start, clusters[i].end); newstart = 1; for (; vAddr < clusters[i].end; vAddr += 0x1000) { unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, vAddr); if (vAddr == out_pc) code_init(mem, vAddr, pageSize, dsmPages, virtualAddrs, 1, calledPages, &codePageNo); else code_init(mem, vAddr, pageSize, dsmPages, virtualAddrs, 0, calledPages, &codePageNo); } ranges[range_index].end = clusters[i].end; } if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } printf("step2, cluster: %d\n", cr3PagesNo); printf("step3, cluster: %d,time cost is %d milliseconds\n", range_index, timeval_diff(NULL, &later, &earlier) / 1000); //3.find the kernel core code page cluster, and print it int osNumber = initDb(); if (gettimeofday(&earlier, NULL)) { perror("gettimeofday() error"); exit(1); } int max_len = 0, max_index = 0; for (i = 1; i <= range_index; i++) { // printf("start:%x, end:%x: len:%x kernel\n", ranges[i].start, ranges[i].end, ranges[i].len); if (ranges[i].len > max_len) { max_index = i; max_len = ranges[i].len; } } //4.print md5 of pages that can be disassembled int availableOs[FINGERPRINT_NO], matchCounts[FINGERPRINT_NO]; for (i = 0; i < FINGERPRINT_NO; i++) { availableOs[i] = 1; matchCounts[i] = 0; } startVirtualAddr = ranges[max_index].start; unsigned disasPageNo = 0; unsigned totalPageNo = 0; for (; startVirtualAddr <= ranges[max_index].end; startVirtualAddr += 0x1000) { totalPageNo++; unsigned pAddr = vtop(mem->mem, mem->mem_size, mem->pgd, startVirtualAddr); if (pAddr == -1 || pAddr > mem->mem_size) continue; int pageIndex = pAddr / pageSize; if (dsmPages[pageIndex] == 1) { int offset = (startVirtualAddr - ranges[max_index].start) / 4096; void *startAdress = (void *) ((unsigned) mem->mem + pageIndex * pageSize); unsigned char md5digest[16]; MDMem(startAdress, pageSize, md5digest); // printf("%x ", vaddr); //print vaddr MDPrint(md5digest); printf("\n"); //search hash table int ret = matchByIndex(osNumber, md5digest, offset, availableOs, matchCounts); // genMd5WithOffset(startAdress, pageSize, startVirtualAddr, offset); disasPageNo++; } } if (gettimeofday(&later, NULL)) { perror("gettimeofday() error"); exit(1); } printf("step4.time cost is %d milliseconds\n", timeval_diff(NULL, &later, &earlier) / 1000); int maxIndex = -1; int maxMatch = 0; for (i = 0; i < FINGERPRINT_NO; i++) { if (matchCounts[i] > maxMatch) { maxIndex = i; maxMatch = matchCounts[i]; } } if (maxMatch > 0) printf("Os is %s, match count is %d\n", fingerprints[maxIndex].osVersion, maxMatch); else puts("Unknown OS!"); return; }
int main(int argc, char **argv) { unsigned long long phys; long total; char *buf, answer[16]; int c, i; int iflag = 0, dflag = 0; time_t now; if (argc <= 1) { usage(); return 0; } pagesize = getpagesize(); while ((c = getopt_long(argc, argv, "dih", opts, NULL)) != -1) { switch (c) { case 'd': dflag = 1; break; case 'i': iflag = 1; break; case 'h': default: usage(); return 0; } } buf = mmap(NULL, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE|MAP_LOCKED, -1, 0); if (buf == MAP_FAILED) { fprintf(stderr, "Can't get a single page of memory!\n"); return 1; } memset(buf, '*', pagesize); phys = vtop((unsigned long long)buf); if (phys == 0) { fprintf(stderr, "Can't get physical address of the page!\n"); return 1; } if (iflag) memcpy(buf, (void*)dummyfunc, pagesize); printf("physical address of (0x%llx) = 0x%llx\n" "Hit any key to trigger error: ", (unsigned long long)buf, phys); fflush(stdout); read(0, answer, 16); now = time(NULL); printf("Access time at %s\n", ctime(&now)); if (iflag) { void (*f)(void) = (void (*)(void))buf; while (1) f() ; } if (dflag) { while (1) { for (i = 0; i < pagesize; i += sizeof(int)) total += *(int*)(buf + i); } } return 0; }