/*## (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.lang.reflect.*;
import java.util.*;
import java.io.*;
import sun.misc.*;

public class SysEnv {
 public static final int PROPS_PAD = 38;
 public static final int USER_PAD  = 10;
 public static final int PID_PAD   = 7;

 public static final String stbprops[] = {
  "iti.app.config", 
  "iti.app.trustedIds", 
  "iti.app.previous.type", 
  "iti.app.fs.cleanup.data", 
  "iti.app.fs.cleanup.step", 
  "iti.app.fs.cleanup.counter", 
  "iti.app.multiboxIds", 
  "iti.app.multiboxTimeout", 
  "iti.app.nVODnet.freePlayCount",
  "iti.app.packetbits",
  "iti.app.extHwVersion",
  "iti.app.scpin",
  "fdt_AppVer",
  "fdt_FactoryResetFlag",
  "ldr.img.app.sec",
  "ldr.img.btr.hw",
  "ldr.img.ldr.ver.short",
  "ldr.img.app.ver.short",
  "mac.STB.Eth.Ethernet",
  "ncp.app.multiboxCode",
  "NAGRA_SCAN_MODE",
  "sn",
  "hnsec.init", 
  "customer_id_variant", 
 };


 private static String dopad(int num) {
  String str="";

  for(int i=0;i<num;i++) {
   str+=" ";
  }

  return str;
 }

 private static void print_tg(ThreadGroup tg,int lvl) {
  try {
   Class c=Class.forName("java.lang.ThreadGroup");

   Field fg=c.getDeclaredField("groups");
   fg.setAccessible(true);

   Field ft=c.getDeclaredField("threads");
   ft.setAccessible(true);

   Thread threads[]=(Thread[])ft.get(tg);
   ThreadGroup groups[]=(ThreadGroup[])fg.get(tg);

   String str=dopad(lvl*2);

   Output.text(str+"GROUP "+tg);

   if (groups!=null) {
    for(int i=0;i<groups.length;i++) {
     if (groups[i]!=null) print_tg(groups[i],lvl+1);
    }
   }

   if (threads!=null) {
    for(int i=0;i<threads.length;i++) {
     if (threads[i]!=null) Output.text(str+" - "+threads[i]);
    }
   }
  } catch(Throwable t) {}
 }

 private static ThreadGroup get_root_grup() {
  ThreadGroup group=Thread.currentThread().getThreadGroup();

  while(group.getParent()!=null) {
   group=group.getParent();
  }
  
  return group;
 }

 public static void jvm_print_threads() {
  int pid=CVM.attachProcess(-1);

  print_tg(get_root_grup(),0);

  CVM.detachProcess(pid);
 }  

 public static void jvm_print_props() throws Throwable {
  Properties props=System.getProperties();
  Enumeration e=props.propertyNames();

  while(e.hasMoreElements()) {
   String name=(String)e.nextElement();
   String value=(String)props.getProperty(name);

   String s=Utils.padded_string(name,PROPS_PAD)+" = "+value;
   Output.text(s);
  }
 }

 public static void jvm_put_prop(String name,String val) {
  try {
   Class c=Class.forName("java.lang.System");
   Field f=c.getDeclaredField("props");
   f.setAccessible(true);

   Properties props=(Properties)f.get(null);

   props.put(name,val);
  } catch(Throwable t) {
   ApiMonitor.log("exc: +t");
  }
 }

 private static void print_ps_info(String name) throws Throwable {
  try {
   int pid=Integer.decode(name).intValue();

   String pdir="/proc/"+name;

   int stat[]=FS.stat_file(pdir);

   if (stat!=null) {
    int uid=stat[2];

    byte data[]=FS.sys_get_proc_file(pdir+"/status");

    if (data!=null) {
     String cmd=null;

     if (FS.read_link(pdir+"/exe")!=null) {
      data=FS.sys_get_proc_file(pdir+"/cmdline");
      cmd=new String(data);
     } else {
      ByteArrayInputStream in=new ByteArrayInputStream(data);
      BufferedReader b=new BufferedReader(new InputStreamReader(in,"utf-8"));

      String line=b.readLine();
      b.close();
      in.close();

      int idx=line.indexOf(":");

      if (idx>0) {
       line=line.substring(idx+1,line.length());

       for(int i=0;i<line.length();i++) {
        if (!Character.isWhitespace(line.charAt(i))) {
         cmd="["+line.substring(i,line.length())+"]";
         break;      
        }
       }
      }
     }

     String user=EtcPasswd.username(uid);

     String uginfo=" "+Utils.padded_string(user,FSDefs.SYS_USR_PAD);

     String line=Utils.padded_string(user,USER_PAD)+Utils.padded_string(""+pid,PID_PAD)+"  "+cmd;
     Output.text(line);
    }
   }
  
  } catch(Throwable t) {}
 }

 public static void sys_print_processes() throws Throwable {
  String dir[]=FS.read_dir("/proc");

  if (dir.length>0) {
   String line=Utils.padded_string("UID",USER_PAD)+Utils.padded_string("PID",PID_PAD)+"  "+"CMD";
   Output.text(line);

   for(int i=0;i<dir.length;i++) {
    char c=dir[i].charAt(0);

    if (Character.isDigit(c)) {
     print_ps_info(dir[i]);
    }
   }
  }
 }

 public static String stb_get_prop(String prop) {
  String res="";

  try {
   Class c=Class.forName("tv.osmosys.tci.device.DeviceFactory");

   Class ctab[]=new Class[1];
   ctab[0]=Class.forName("java.lang.String");

   Method open=c.getMethod("openDevice",ctab);

   Object args[]=new Object[1];
   args[0]="stbdata";

   Object deviceproxy=open.invoke(null,args);

   c=Class.forName("tv.osmosys.tci.device.DeviceProxy");

   Method getmethod=c.getMethod("getMethod",ctab);

   args[0]="get_property(S)S";

   Object id=getmethod.invoke(deviceproxy,args);

   ctab=new Class[2];
   ctab[0]=Integer.TYPE;
   ctab[1]=Class.forName("java.lang.Object");

   Method control=c.getMethod("control",ctab);

   args=new Object[2];
   args[0]=id;
   args[1]=prop;   

   res=(String)control.invoke(deviceproxy,args);

   Method close=c.getMethod("close",new Class[0]);

   close.invoke(deviceproxy,new Object[0]);
  } catch(Throwable t) {}

  return res;
 }

 public static void stb_print_props() throws Throwable {
  for(int i=0;i<stbprops.length;i++) {
   String name=stbprops[i];
   String value=stb_get_prop(name);

   if (value!=null) {
    String s=Utils.padded_string(name,PROPS_PAD)+" = "+value;
    Output.text(s);
   }
  }
 }
}
