当前位置: 首页 > news >正文

PicoCTF writeup - picoMini —— Pico Bank

Today, We will begin the hardest part of the picoMini writeup——Pico Bank.

Now look at the question


and the hints.



I choose android-killer to inspect the apk.(you can also use other app like apktool or jadxGUI)


Open the pico-bank app in Mumu simulator.

before we login, we must know the password.

Try to find it in the source code!


search "login"


we can see the login.smali.

Click it.


We can find the username and password in the login$1.smali


Login now.

username:johnson password:tricky1990

And we can see this.

Then we need to find the OTP value.


Try to search the OTP.


Find it! So easy.

The otp is 9673


Here is the page after we login.


Look at the notification.

It seems that we need to check the server's responce , so we have to enter the otp again😭.


And we need to investigate the history data.

It looks like binary code, because it is composed of 0 and 1.


Try to write down all the numbers.

1110000 1101001 1100011 1101111 1000011 1010100 1000110 1111011 110001 1011111 1101100 110001 110011 1100100 1011111 110100 1100010 110000 1110101 1110100 1011111 1100010 110011 110001 1101110 1100111 1011111

Throw it to Deepseek,let AI to transfer the binary code into ASCII.


so the first part of the flag is

picoCTF{1_l13d_4b0ut_b31ng_

OK. Now ,we need to find another part of it.

FIRST,try to get some hint in the source code.

We need to find out how the server handle the responce.

# annotations .annotation system Ldalvik/annotation/EnclosingMethod; value = Lcom/example/picobank/OTP;->verifyOtp(Ljava/lang/String;)V .end annotation .annotation system Ldalvik/annotation/InnerClass; accessFlags = 0x0 name = null .end annotation .annotation system Ldalvik/annotation/Signature; value = { "Ljava/lang/Object;", "Lcom/android/volley/Response$Listener<", "Lorg/json/JSONObject;", ">;" } .end annotation # instance fields .field final synthetic this$0:Lcom/example/picobank/OTP; # direct methods .method constructor <init>(Lcom/example/picobank/OTP;)V .locals 0 .param p1, "this$0" # Lcom/example/picobank/OTP; .line 86 iput-object p1, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-direct {p0}, Ljava/lang/Object;-><init>()V return-void .end method .method public onResponse(Lorg/json/JSONObject;)V .locals 8 .param p1, "response" # Lorg/json/JSONObject; .line 90 const-string v0, "hint" const-string v1, "flag" :try_start_0 const-string v2, "success" invoke-virtual {p1, v2}, Lorg/json/JSONObject;->getBoolean(Ljava/lang/String;)Z move-result v2 .line 91 .local v2, "success":Z if-eqz v2, :cond_0 .line 92 invoke-virtual {p1, v1}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v3 .line 93 .local v3, "flag":Ljava/lang/String; invoke-virtual {p1, v0}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String; move-result-object v4 .line 95 .local v4, "hint":Ljava/lang/String; new-instance v5, Landroid/content/Intent; iget-object v6, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-class v7, Lcom/example/picobank/MainActivity; invoke-direct {v5, v6, v7}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 96 .local v5, "intent":Landroid/content/Intent; invoke-virtual {v5, v1, v3}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 97 invoke-virtual {v5, v0, v4}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent; .line 98 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0, v5}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 99 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; invoke-virtual {v0}, Lcom/example/picobank/OTP;->finish()V .line 100 .end local v3 # "flag":Ljava/lang/String; .end local v4 # "hint":Ljava/lang/String; .end local v5 # "intent":Landroid/content/Intent; goto :goto_0 .line 101 :cond_0 iget-object v0, p0, Lcom/example/picobank/OTP$2;->this$0:Lcom/example/picobank/OTP; const-string v1, "Invalid OTP"

We know that, the otp_value was firstly passed to VERIFYOTP , then, if the value is correct ,we can see the flag.

Try search the verifyotp

.method private verifyOtp(Ljava/lang/String;)V .locals 10 .param p1, "otp" # Ljava/lang/String; .line 67 const-string v0, "your server url" .line 68 .local v0, "severUrl":Ljava/lang/String; new-instance v1, Ljava/lang/StringBuilder; invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 const-string v2, "/verify-otp" invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v1 .line 70 .local v1, "endpoint":Ljava/lang/String; invoke-virtual {p0}, Lcom/example/picobank/OTP;->getResources()Landroid/content/res/Resources; move-result-object v2 sget v3, Lcom/example/picobank/R$string;->otp_value:I invoke-virtual {v2, v3}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String; move-result-object v2 invoke-virtual {v2, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z move-result v2 if-eqz v2, :cond_0 .line 71 new-instance v2, Landroid/content/Intent; const-class v3, Lcom/example/picobank/MainActivity; invoke-direct {v2, p0, v3}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V .line 72 .local v2, "intent":Landroid/content/Intent; invoke-virtual {p0, v2}, Lcom/example/picobank/OTP;->startActivity(Landroid/content/Intent;)V .line 73 invoke-virtual {p0}, Lcom/example/picobank/OTP;->finish()V .line 74 .end local v2 # "intent":Landroid/content/Intent; goto :goto_0 .line 75 :cond_0 const-string v2, "Invalid OTP"

Here in the code , our server url is connected with the "/verify-otp".

like this.


And then we need to POST the otpvalue to server .

Use burpsuite.


Don't forget to add the Content-type , otherwise it will fail.


Here is the response.


So the second part of the flag is

s3cur3d_m0b1l3_l0g1n_e9d3786f}

OK! Still so easy today!🥳See you!

flag

picoCTF{1_l13d_4b0ut_b31ng_s3cur3d_m0b1l3_l0g1n_e9d3786f}
http://www.cnnetsun.cn/news/88067.html

相关文章:

  • 开源5G基站硬件参数
  • C#开发桌面应用调用GPT-SoVITS REST API实战
  • Dify Docker部署与使用全指南
  • 数组作为参数
  • 蜜罐技术-德迅猎鹰
  • Daily Report — Day 9 (Beta)
  • Seed-Coder-8B-Base与SonarQube智能集成路径
  • 基于CentOS7 DM8单机部署配置记录-20251216
  • 大模型入门:预训练、微调和蒸馏,一篇文章全掌握
  • LobeChat能否编写教案?教师备课自动化尝试
  • vLLM-Omni:全模态AI推理框架技术解析
  • 18、基于位置点的恢复
  • LobeChat文件上传与语音交互实测:这些功能太惊艳了
  • LobeChat日志记录与审计功能配置方法说明
  • Qwen3-8B接入MCP实现动态工具调用
  • Docker 从入门到精通教程
  • waitGroup底层源码分析
  • LobeChat能否用于编写Prometheus告警规则?可观测性增强
  • 大模型学习全攻略:七阶段系统学习路线图,从基础到实战应用,非常详细收藏我这一篇就够了
  • 玄晶引擎AI数字员工更新深度测评:Sora2赋能+RPA运营,AI内容生产进入效率革命期
  • YOLOv5中使用torch加载自定义模型进行目标检测
  • LobeChat能否隐藏源码信息?增强系统隐蔽性
  • React 的桶算法详解
  • 深入理解Dify的依赖管理机制(Dependency Walker适用场景)
  • CordovaOpenHarmony车辆管理系统开发
  • YOLO训练中断恢复技巧:避免重复计算
  • 电气自动化专业相关认证解析
  • 手机内存告急?MAZANOKE 压缩照片不损画质,加载cpolar远程用更方便
  • 「直通」英伟达,蓝思科技补齐AI算力布局又一块拼图
  • Dify + Jenkins 实现AI应用持续集成与自动化部署