/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.io.*;
import java.util.*;

public class KModule {
 public static final String MODULES="/proc/modules";
 public static final String MODULESPATH="/lib/modules/";

 public static final int BUFSIZE=0x2000;

 private static Hashtable mods;
 private static Hashtable syms;

 private static void parse_module(String mdata) {
  String mname=null;
  int maddr=0;

  int idx=mdata.indexOf(' ');
  if (idx>0) {
   mname=mdata.substring(0,idx);
   idx=mdata.indexOf("Live ");
   if (idx>0) {
    String s=mdata.substring(idx+7,mdata.length());
    maddr=Utils.parse_hex(s);

    mods.put(mname,new Integer(maddr));
   }
  }
 }

 private static void parse_modules(String data) {
  try {
   ByteArrayInputStream bais=new ByteArrayInputStream(data.getBytes());
   BufferedReader b=new BufferedReader(new InputStreamReader(bais,"utf-8"));

   String line=b.readLine();

   while(line!=null) {
    parse_module(line);
    line=b.readLine();
   }

   b.close();
   bais.close();
  } catch(Throwable t) {}
 }

 static {
  mods=new Hashtable();
  syms=new Hashtable();

  NativeCode nc=NativeCode.getInstance();

  int buf=nc.malloc(BUFSIZE);

  int fd=RootAccess.open(MODULES,0);
  int len=RootAccess.read(fd,buf,BUFSIZE);
  RootAccess.close(fd);

  String data=Utils.buf2javastring(buf,len);  

  parse_modules(data);

  nc.free(buf);
 }

 public static int get_base(String name) {
  Integer val=(Integer)mods.get(name);

  if (val!=null) {
   return val.intValue();
  }

  return 0;
 }


 public static int get_sym_addr(String modname,String name) {
  Integer val=(Integer)mods.get(modname);

  if (val!=null) {
   ELFUtils e=(ELFUtils)syms.get(modname);

   if (e==null) {   
    String path=MODULESPATH+modname+".ko";
    int size=RootAccess.filesize(path);

    if (size>0) {
     NativeCode nc=NativeCode.getInstance();

     int buf=nc.malloc(size);

     int fd=RootAccess.open(path,RootAccess.O_RDONLY);
     int len=RootAccess.read(fd,buf,size);
     RootAccess.close(fd);

     e=new ELFUtils(buf);
     syms.put(modname,e);
    }
   }

   return val.intValue()+e.get_sym_addr(name);
  }

  return 0;
 }

}
